openstudio-standards 0.2.16 → 0.2.17.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/data/standards/manage_OpenStudio_Standards.rb +31 -4
  3. data/lib/openstudio-standards/btap/geometry.rb +1 -1
  4. data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +354 -2
  5. data/lib/openstudio-standards/hvac_sizing/Siz.ThermalZone.rb +79 -0
  6. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.College.rb +1 -1
  7. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.Laboratory.rb +1 -1
  8. data/lib/openstudio-standards/prototypes/common/do_not_edit_metaclasses.rb +3313 -0
  9. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Fan.rb +12 -0
  10. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +3 -4
  11. data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +1 -1
  12. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +167 -93
  13. data/lib/openstudio-standards/prototypes/common/objects/Prototype.utilities.rb +2 -4
  14. data/lib/openstudio-standards/prototypes/common/prototype_metaprogramming.rb +1 -0
  15. data/lib/openstudio-standards/refs/references.rb +3 -0
  16. data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +279 -6
  17. data/lib/openstudio-standards/standards/Standards.AirTerminalSingleDuctParallelPIUReheat.rb +50 -2
  18. data/lib/openstudio-standards/standards/Standards.ChillerElectricEIR.rb +4 -0
  19. data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +0 -1
  20. data/lib/openstudio-standards/standards/Standards.Construction.rb +185 -3
  21. data/lib/openstudio-standards/standards/Standards.Fan.rb +14 -6
  22. data/lib/openstudio-standards/standards/Standards.HeatExchangerSensLat.rb +1 -0
  23. data/lib/openstudio-standards/standards/Standards.Model.rb +1751 -383
  24. data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +130 -9
  25. data/lib/openstudio-standards/standards/Standards.PlantLoop.rb +50 -3
  26. data/lib/openstudio-standards/standards/Standards.ScheduleCompact.rb +44 -0
  27. data/lib/openstudio-standards/standards/Standards.ScheduleConstant.rb +27 -0
  28. data/lib/openstudio-standards/standards/Standards.ScheduleRuleset.rb +543 -0
  29. data/lib/openstudio-standards/standards/Standards.Space.rb +665 -15
  30. data/lib/openstudio-standards/standards/Standards.SpaceType.rb +141 -4
  31. data/lib/openstudio-standards/standards/Standards.SubSurface.rb +2 -1
  32. data/lib/openstudio-standards/standards/Standards.Surface.rb +117 -0
  33. data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +197 -49
  34. data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +41 -0
  35. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Model.rb +6 -8
  36. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/comstock_ashrae_90_1_2004/data/ashrae_90_1.schedules.json +45 -45
  37. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/comstock_ashrae_90_1_2004/data/comstock_ashrae_90_1_2004.spc_typ.json +7 -7
  38. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/comstock_ashrae_90_1_2007/data/ashrae_90_1.schedules.json +45 -45
  39. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/comstock_ashrae_90_1_2007/data/comstock_ashrae_90_1_2007.spc_typ.json +7 -7
  40. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/comstock_ashrae_90_1_2010/data/ashrae_90_1.schedules.json +45 -45
  41. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/comstock_ashrae_90_1_2010/data/comstock_ashrae_90_1_2010.spc_typ.json +9 -9
  42. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/comstock_ashrae_90_1_2013/data/ashrae_90_1.schedules.json +45 -45
  43. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/comstock_ashrae_90_1_2013/data/comstock_ashrae_90_1_2013.spc_typ.json +4 -4
  44. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/data/ashrae_90_1.schedules.json +45 -45
  45. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/comstock_ashrae_90_1_2016/data/comstock_ashrae_90_1_2016.spc_typ.json +5 -5
  46. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +5 -5
  47. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/data/ashrae_90_1.schedules.json +45 -45
  48. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/comstock_ashrae_90_1_2019/data/comstock_ashrae_90_1_2019.spc_typ.json +5 -5
  49. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.constructions.json +2 -2
  50. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.fans.json +12 -0
  51. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/comstock_doe_ref_1980_2004/data/ashrae_90_1.schedules.json +45 -45
  52. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/comstock_doe_ref_1980_2004/data/comstock_doe_ref_1980_2004.spc_typ.json +10 -10
  53. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/comstock_doe_ref_pre_1980/data/ashrae_90_1.schedules.json +45 -45
  54. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/comstock_doe_ref_pre_1980/data/comstock_doe_ref_pre_1980.spc_typ.json +10 -10
  55. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/nrel_zne_ready_2017.AirLoopHVAC.rb +1 -0
  56. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +792 -0
  57. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctParallelPIUReheat.rb +10 -0
  58. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirTerminalSingleDuctVAVReheat.rb +31 -0
  59. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.BoilerHotWater.rb +91 -0
  60. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ChillerElectricEIR.rb +84 -0
  61. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXSingleSpeed.rb +145 -0
  62. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilCoolingDXTwoSpeed.rb +106 -0
  63. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilDX.rb +71 -0
  64. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingDXSingleSpeed.rb +194 -0
  65. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoilHeatingGas.rb +120 -0
  66. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTower.rb +110 -0
  67. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.CoolingTowerVariableSpeed.rb +5 -0
  68. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Fan.rb +73 -0
  69. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanConstantVolume.rb +5 -0
  70. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanOnOff.rb +5 -0
  71. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanVariableVolume.rb +24 -0
  72. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.FanZoneExhaust.rb +5 -0
  73. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.HeatExchangerSensLat.rb +55 -0
  74. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +3045 -0
  75. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlanarSurface.rb +187 -0
  76. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +450 -0
  77. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Space.rb +106 -0
  78. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.SpaceType.rb +666 -0
  79. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Surface.rb +54 -0
  80. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ThermalZone.rb +168 -0
  81. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.ZoneHVACComponent.rb +132 -0
  82. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.rb +239 -0
  83. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb +176 -0
  84. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.rb +25 -0
  85. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.boilers.json +52 -0
  86. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.chillers.json +112 -0
  87. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.climate_zone_sets.json +210 -0
  88. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.construction_properties.json +10384 -0
  89. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.construction_sets.json +133 -0
  90. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.furnaces.json +43 -0
  91. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.heat_pumps.json +119 -0
  92. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.heat_pumps_heating.json +130 -0
  93. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.heat_rejection.json +13 -0
  94. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.lpd_space_type.json +568 -0
  95. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.motors.json +264 -0
  96. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_baseline_hvac.json +439 -0
  97. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_constructions.json +685 -0
  98. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_economizers.json +213 -0
  99. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_ext_ltg.json +32 -0
  100. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_heat_type.json +136 -0
  101. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_hvac_bldg_type.json +32 -0
  102. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_interior_lighting.json +1837 -0
  103. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_swh_bldg_type.json +184 -0
  104. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_wwr_bldg_type.json +84 -0
  105. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.unitary_acs.json +148 -0
  106. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.water_heaters.json +157 -0
  107. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.climate_zone_sets.json +210 -0
  108. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.curves.json +18329 -0
  109. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.fans.json +340 -0
  110. data/lib/openstudio-standards/standards/ashrae_90_1_prm/data/ashrae_90_1_prm.materials.json +49924 -0
  111. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/baseline_building_rotation_exception.md +44 -0
  112. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/check_pump_power_and_control.md +71 -0
  113. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/dcv.md +68 -0
  114. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/dcv_implementation.png +0 -0
  115. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/elevators.md +14 -0
  116. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/exhaust_air_energy_recovery.md +36 -0
  117. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/f_c_factors.md +19 -0
  118. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/fan_power_credits.md +15 -0
  119. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/preheat_coil.md +59 -0
  120. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/pump_power_control.md +46 -0
  121. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/return_air_type.md +31 -0
  122. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_baseline_wwr.md +191 -0
  123. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_hw_and_chw_supply_water_temp_reset_control.md +24 -0
  124. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_num_boilers_chillers_towers.md +49 -0
  125. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_plug_load_measures.md +80 -0
  126. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/set_space_lpd.md +73 -0
  127. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/unenclosed_and_unconditioned_spaces.md +11 -0
  128. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/unmet_load_hours.md +20 -0
  129. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/vav_parallel_piu_terminals_fan_control.md +23 -0
  130. data/lib/openstudio-standards/standards/ashrae_90_1_prm/docs/vav_terminals_min_flow_setpoint.md +21 -0
  131. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_airloop_hvac.csv +1 -0
  132. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_airloop_hvac_doas.csv +1 -0
  133. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_building.csv +1 -0
  134. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_design_specification_outdoor_air.csv +1 -0
  135. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_electric_equipment.csv +1 -0
  136. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_exterior_lights.csv +1 -0
  137. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_gas_equipment.csv +1 -0
  138. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_lights.csv +1 -0
  139. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_space.csv +1 -0
  140. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_spacetype.csv +1 -0
  141. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_thermal_zone.csv +1 -0
  142. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_connections.csv +1 -0
  143. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_equipment.csv +1 -0
  144. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_wateruse_equipment_definition.csv +1 -0
  145. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_zone_hvac.csv +1 -0
  146. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/userdata_zone_infiltration.csv +1 -0
  147. data/lib/openstudio-standards/standards/cbes/data/cbes.fans.json +12 -0
  148. data/lib/openstudio-standards/standards/deer/data/deer.fans.json +12 -0
  149. data/lib/openstudio-standards/standards/necb/ECMS/data/heat_pumps.json +1 -1
  150. data/lib/openstudio-standards/standards/necb/ECMS/data/heat_pumps_heating.json +1 -1
  151. data/lib/openstudio-standards/standards/necb/ECMS/data/unitary_acs.json +24 -11
  152. data/lib/openstudio-standards/standards/necb/ECMS/erv.rb +13 -15
  153. data/lib/openstudio-standards/standards/necb/NECB2011/data/province_map.json +17 -0
  154. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_multi_speed.rb +1 -1
  155. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_single_speed.rb +1 -1
  156. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_4.rb +2 -2
  157. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_6.rb +6 -5
  158. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +3 -2
  159. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +2 -3
  160. data/lib/openstudio-standards/standards/necb/NECB2020/data/chillers.json +2 -2
  161. data/lib/openstudio-standards/standards/necb/NECB2020/data/space_types.json +33 -924
  162. data/lib/openstudio-standards/standards/necb/NECB2020/data/unitary_acs.json +15 -15
  163. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +135 -29
  164. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +16 -4
  165. data/lib/openstudio-standards/standards/necb/common/neb_end_use_prices.csv +40 -42
  166. data/lib/openstudio-standards/standards/necb/common/necb_reference_runs.csv +1 -1
  167. data/lib/openstudio-standards/standards/necb/common/space_type_upgrade_map.json +89 -89
  168. data/lib/openstudio-standards/utilities/array.rb +11 -0
  169. data/lib/openstudio-standards/utilities/logging.rb +48 -0
  170. data/lib/openstudio-standards/utilities/object_info.rb +20 -0
  171. data/lib/openstudio-standards/utilities/schedule_translator.rb +348 -0
  172. data/lib/openstudio-standards/utilities/sqlfile.rb +68 -0
  173. data/lib/openstudio-standards/version.rb +2 -2
  174. data/lib/openstudio-standards/weather/Weather.Model.rb +42 -55
  175. data/lib/openstudio-standards/weather/Weather.stat_file.rb +1 -1
  176. data/lib/openstudio-standards.rb +35 -1
  177. metadata +111 -6
  178. data/data/standards/OpenStudio_Standards-ashrae_90_1.xlsx +0 -0
  179. data/data/standards/OpenStudio_Standards-ashrae_90_1_28Jan2022.xlsx +0 -0
  180. data/data/standards/OpenStudio_Standards-ashrae_90_1_28_Jan2022_2.xlsx +0 -0
  181. data/data/standards/openstudio_standards_duplicates_log.csv +0 -143
@@ -0,0 +1,187 @@
1
+ class ASHRAE901PRM < Standard
2
+ # @!group PlanarSurface
3
+
4
+ # If construction properties can be found based on the template,
5
+ # the standards intended surface type, the standards construction type,
6
+ # the climate zone, and the occupancy type,
7
+ # create a construction that meets those properties and assign it to this surface.
8
+ # 90.1-PRM-2019
9
+ #
10
+ # @param planar_surface [Openstudio::Model:PlanarSurface] surface object
11
+ # @param climate_zone [String] ASHRAE climate zone, e.g. 'ASHRAE 169-2013-4A'
12
+ # @param previous_construction_map [Hash] a hash where the keys are an array of inputs
13
+ # [template, climate_zone, intended_surface_type, standards_construction_type, occ_type]
14
+ # and the values are the constructions. If supplied, constructions will be pulled
15
+ # from this hash if already created to avoid creating duplicate constructions.
16
+ # @return [Hash] returns a hash where the key is an array of inputs
17
+ # [template, climate_zone, intended_surface_type, standards_construction_type, occ_type]
18
+ # and the value is the newly created construction.
19
+ # This can be used to avoid creating duplicate constructions.
20
+ # @todo Align the standard construction enumerations in the
21
+ # spreadsheet with the enumerations in OpenStudio (follow CBECC-Com).
22
+ def planar_surface_apply_standard_construction(planar_surface, climate_zone, previous_construction_map = {}, wwr_building_type = nil, wwr_info = {}, surface_category)
23
+ # Skip surfaces not in a space
24
+ return previous_construction_map if planar_surface.space.empty?
25
+
26
+ space = planar_surface.space.get
27
+ if surface_category == 'ExteriorSubSurface'
28
+ surface_type = planar_surface.subSurfaceType
29
+ else
30
+ surface_type = planar_surface.surfaceType
31
+ end
32
+
33
+ # Skip surfaces that don't have a construction
34
+ # return previous_construction_map if planar_surface.construction.empty?
35
+ if !planar_surface.construction.empty?
36
+ construction = planar_surface.construction.get
37
+ else
38
+ # Get appropriate default construction if not defined inside surface object
39
+ construction = nil
40
+ space_type = space.spaceType.get
41
+ if space.defaultConstructionSet.is_initialized
42
+ cons_set = space.defaultConstructionSet.get
43
+ construction = get_default_surface_cons_from_surface_type(surface_category, surface_type, cons_set)
44
+ end
45
+ if construction.nil? && space_type.defaultConstructionSet.is_initialized
46
+ cons_set = space_type.defaultConstructionSet.get
47
+ construction = get_default_surface_cons_from_surface_type(surface_category, surface_type, cons_set)
48
+ end
49
+ if construction.nil? && space.buildingStory.get.defaultConstructionSet.is_initialized
50
+ cons_set = space.buildingStory.get.defaultConstructionSet.get
51
+ construction = get_default_surface_cons_from_surface_type(surface_category, surface_type, cons_set)
52
+ end
53
+ if construction.nil? && space.model.building.get.defaultConstructionSet.is_initialized
54
+ cons_set = space.model.building.get.defaultConstructionSet.get
55
+ construction = get_default_surface_cons_from_surface_type(surface_category, surface_type, cons_set)
56
+ end
57
+
58
+ return previous_construction_map if construction.nil?
59
+ end
60
+
61
+ # Determine if residential or nonresidential
62
+ # based on the space type.
63
+ occ_type = 'Nonresidential'
64
+ if space_residential?(space)
65
+ occ_type = 'Residential'
66
+ end
67
+
68
+ # Get the climate zone set
69
+ climate_zone_set = model_find_climate_zone_set(planar_surface.model, climate_zone)
70
+
71
+ # Get the intended surface type
72
+ standards_info = construction.standardsInformation
73
+ surf_type = standards_info.intendedSurfaceType
74
+
75
+ if surf_type.empty?
76
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlanarSurface', "Could not determine the intended surface type for #{planar_surface.name} from #{construction.name}. This surface will not have the standard applied.")
77
+ return previous_construction_map
78
+ end
79
+ surf_type = surf_type.get
80
+
81
+ # Get the standards type, which is based on different fields
82
+ # if is intended for a window, a skylight, or something else.
83
+ # Mapping is between standards-defined enumerations and the
84
+ # enumerations available in OpenStudio.
85
+ stds_type = nil
86
+ # Windows and Glass Doors
87
+ if surf_type == 'ExteriorWindow' || surf_type == 'GlassDoor'
88
+ stds_type = standards_info.fenestrationFrameType
89
+ if stds_type.is_initialized
90
+ stds_type = stds_type.get
91
+ if !wwr_building_type.nil?
92
+ stds_type = 'Any Vertical Glazing'
93
+ end
94
+ case stds_type
95
+ when 'Metal Framing', 'Metal Framing with Thermal Break'
96
+ stds_type = 'Metal framing (all other)'
97
+ when 'Non-Metal Framing'
98
+ stds_type = 'Nonmetal framing (all)'
99
+ when 'Any Vertical Glazing'
100
+ stds_type = 'Any Vertical Glazing'
101
+ else
102
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlanarSurface', "The standards fenestration frame type #{stds_type} cannot be used on #{surf_type} in #{planar_surface.name}. This surface will not have the standard applied.")
103
+ return previous_construction_map
104
+ end
105
+ else
106
+ if !wwr_building_type.nil?
107
+ stds_type = 'Any Vertical Glazing'
108
+ else
109
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlanarSurface', "Could not determine the standards fenestration frame type for #{planar_surface.name} from #{construction.name}. This surface will not have the standard applied.")
110
+ return previous_construction_map
111
+ end
112
+ end
113
+ # Exterior Doors
114
+ elsif surf_type == 'ExteriorDoor'
115
+ stds_type = standards_info.standardsConstructionType
116
+ if stds_type.is_initialized
117
+ stds_type = stds_type.get
118
+ case stds_type
119
+ when 'RollUp'
120
+ stds_type = 'NonSwinging'
121
+ end
122
+ else
123
+ stds_type = 'Swinging'
124
+ end
125
+ # Skylights
126
+ elsif surf_type == 'Skylight'
127
+ # There is only one type for AppendixG stable baseline
128
+ stds_type = 'Any Skylight'
129
+ # All other surface types
130
+ else
131
+ stds_type = standards_info.standardsConstructionType
132
+ if stds_type.is_initialized
133
+ stds_type = stds_type.get
134
+ else
135
+ if planar_surface.outsideBoundaryCondition == 'Surface' && surface_category == 'NA'
136
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.PlanarSurface', "Standards construction is not needed and not applied for interior wall: #{planar_surface.name}.")
137
+ else
138
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlanarSurface', "Could not determine the standards construction type for #{planar_surface.name}. This surface will not have the standard applied.")
139
+ end
140
+ return previous_construction_map
141
+ end
142
+ end
143
+
144
+ # Check if the construction type was already created.
145
+ # If yes, use that construction. If no, make a new one.
146
+
147
+ # for multi-building type - search for the surface wwr type
148
+ surface_std_wwr_type = wwr_building_type
149
+ new_construction = nil
150
+ type = [template, climate_zone, surf_type, stds_type, occ_type]
151
+ # Only apply the surface_std_wwr_type update when wwr_building_type has Truthy values
152
+ if !wwr_building_type.nil? && (surf_type == 'ExteriorWindow' || surf_type == 'GlassDoor')
153
+ space = planar_surface.space.get
154
+ if space.hasAdditionalProperties && space.additionalProperties.hasFeature('building_type_for_wwr')
155
+ surface_std_wwr_type = space.additionalProperties.getFeatureAsString('building_type_for_wwr').get
156
+ end
157
+ type.push(surface_std_wwr_type)
158
+ end
159
+
160
+ if previous_construction_map[type] && !previous_construction_map[type].iddObjectType.valueName.to_s.include?('factorGround')
161
+ new_construction = previous_construction_map[type]
162
+ else
163
+ new_construction = model_find_and_add_construction(planar_surface.model,
164
+ climate_zone_set,
165
+ surf_type,
166
+ stds_type,
167
+ occ_type,
168
+ wwr_building_type: surface_std_wwr_type,
169
+ wwr_info: wwr_info,
170
+ surface: planar_surface)
171
+ if !new_construction == false
172
+ previous_construction_map[type] = new_construction
173
+ end
174
+ end
175
+
176
+ # Assign the new construction to the surface
177
+ if new_construction
178
+ planar_surface.setConstruction(new_construction)
179
+ OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.PlanarSurface', "Set the construction for #{planar_surface.name} to #{new_construction.name}.")
180
+ else
181
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlanarSurface', "Could not generate a standard construction for #{planar_surface.name}.")
182
+ return previous_construction_map
183
+ end
184
+
185
+ return previous_construction_map
186
+ end
187
+ end
@@ -0,0 +1,450 @@
1
+ class ASHRAE901PRM < Standard
2
+ # Keep only one cooling tower, but use one condenser pump per chiller
3
+
4
+ # @param plant_loop [OpenStudio::Model::PlantLoop] plant loop
5
+ # @return [Bool] returns true if successful, false if not
6
+ def plant_loop_apply_prm_number_of_cooling_towers(plant_loop)
7
+ # Skip non-cooling plants
8
+ return true unless plant_loop.sizingPlant.loopType == 'Condenser'
9
+
10
+ # Determine the number of chillers
11
+ # already in the model
12
+ num_chillers = plant_loop.model.getChillerElectricEIRs.size
13
+
14
+ # Get all existing cooling towers and pumps
15
+ clg_twrs = []
16
+ pumps = []
17
+ plant_loop.supplyComponents.each do |sc|
18
+ if sc.to_CoolingTowerSingleSpeed.is_initialized
19
+ clg_twrs << sc.to_CoolingTowerSingleSpeed.get
20
+ elsif sc.to_CoolingTowerTwoSpeed.is_initialized
21
+ clg_twrs << sc.to_CoolingTowerTwoSpeed.get
22
+ elsif sc.to_CoolingTowerVariableSpeed.is_initialized
23
+ clg_twrs << sc.to_CoolingTowerVariableSpeed.get
24
+ elsif sc.to_PumpConstantSpeed.is_initialized
25
+ pumps << sc.to_PumpConstantSpeed.get
26
+ elsif sc.to_PumpVariableSpeed.is_initialized
27
+ pumps << sc.to_PumpVariableSpeed.get
28
+ end
29
+ end
30
+
31
+ # Ensure there is only 1 cooling tower to start
32
+ orig_twr = nil
33
+ if clg_twrs.size.zero?
34
+ return true
35
+ elsif clg_twrs.size > 1
36
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.PlantLoop', "For #{plant_loop.name}, found #{clg_twrs.size} cooling towers, cannot split up per performance rating method baseline requirements.")
37
+ return false
38
+ else
39
+ orig_twr = clg_twrs[0]
40
+ end
41
+
42
+ # Ensure there is only 1 pump to start
43
+ orig_pump = nil
44
+ if pumps.size.zero?
45
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.PlantLoop', "For #{plant_loop.name}, found #{pumps.size} pumps. A loop must have at least one pump.")
46
+ return false
47
+ elsif pumps.size > 1
48
+ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.PlantLoop', "For #{plant_loop.name}, found #{pumps.size} pumps, cannot split up per performance rating method baseline requirements.")
49
+ return false
50
+ else
51
+ orig_pump = pumps[0]
52
+ end
53
+
54
+ # Determine the per-cooling_tower sizing factor
55
+ clg_twr_sizing_factor = (1.0 / num_chillers).round(2)
56
+
57
+ final_twrs = [orig_twr]
58
+
59
+ # If there is more than one chiller,
60
+ # replace the original pump with a headered pump
61
+ # of the same type and properties.
62
+ if num_chillers > 1
63
+ num_pumps = num_chillers
64
+ new_pump = nil
65
+ if orig_pump.to_PumpConstantSpeed.is_initialized
66
+ new_pump = OpenStudio::Model::HeaderedPumpsConstantSpeed.new(plant_loop.model)
67
+ new_pump.setNumberofPumpsinBank(num_pumps)
68
+ new_pump.setName("#{orig_pump.name} Bank of #{num_pumps}")
69
+ new_pump.setRatedPumpHead(orig_pump.ratedPumpHead)
70
+ new_pump.setMotorEfficiency(orig_pump.motorEfficiency)
71
+ new_pump.setFractionofMotorInefficienciestoFluidStream(orig_pump.fractionofMotorInefficienciestoFluidStream)
72
+ new_pump.setPumpControlType(orig_pump.pumpControlType)
73
+ elsif orig_pump.to_PumpVariableSpeed.is_initialized
74
+ new_pump = OpenStudio::Model::HeaderedPumpsVariableSpeed.new(plant_loop.model)
75
+ new_pump.setNumberofPumpsinBank(num_pumps)
76
+ new_pump.setName("#{orig_pump.name} Bank of #{num_pumps}")
77
+ new_pump.setRatedPumpHead(orig_pump.ratedPumpHead)
78
+ new_pump.setMotorEfficiency(orig_pump.motorEfficiency)
79
+ new_pump.setFractionofMotorInefficienciestoFluidStream(orig_pump.fractionofMotorInefficienciestoFluidStream)
80
+ new_pump.setPumpControlType(orig_pump.pumpControlType)
81
+ new_pump.setCoefficient1ofthePartLoadPerformanceCurve(orig_pump.coefficient1ofthePartLoadPerformanceCurve)
82
+ new_pump.setCoefficient2ofthePartLoadPerformanceCurve(orig_pump.coefficient2ofthePartLoadPerformanceCurve)
83
+ new_pump.setCoefficient3ofthePartLoadPerformanceCurve(orig_pump.coefficient3ofthePartLoadPerformanceCurve)
84
+ new_pump.setCoefficient4ofthePartLoadPerformanceCurve(orig_pump.coefficient4ofthePartLoadPerformanceCurve)
85
+ end
86
+ # Remove the old pump
87
+ orig_pump.remove
88
+ # Attach the new headered pumps
89
+ new_pump.addToNode(plant_loop.supplyInletNode)
90
+ end
91
+ end
92
+
93
+ # Get the total cooling capacity for the plant loop
94
+ #
95
+ # @param plant_loop [OpenStudio::Model::PlantLoop] plant loop
96
+ # @param [String] sizing_run_dir
97
+ # @return [Double] total cooling capacity in watts
98
+ def plant_loop_total_cooling_capacity(plant_loop, sizing_run_dir = Dir.pwd)
99
+ # Sum the cooling capacity for all cooling components
100
+ # on the plant loop.
101
+ total_cooling_capacity_w = 0
102
+ sizing_run_ran = false
103
+
104
+ plant_loop.supplyComponents.each do |sc|
105
+ # ChillerElectricEIR
106
+ if sc.to_ChillerElectricEIR.is_initialized
107
+ chiller = sc.to_ChillerElectricEIR.get
108
+
109
+ # If chiller is autosized, check sizing run results. If sizing run not ran, run it first
110
+ if chiller.isReferenceCapacityAutosized
111
+ model = chiller.model
112
+ sizing_run_ran = model_run_sizing_run(model, "#{sizing_run_dir}/SR_cooling_plant") if !sizing_run_ran
113
+
114
+ if sizing_run_ran
115
+ sizing_run_capacity = model.getAutosizedValueFromEquipmentSummary(chiller, 'Central Plant', 'Nominal Capacity', 'W').get
116
+ chiller.setReferenceCapacity(sizing_run_capacity)
117
+ total_cooling_capacity_w += sizing_run_capacity
118
+ else
119
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlantLoop', "For #{plant_loop.name} capacity of #{chiller.name} is not available due to a sizing run failure, total cooling capacity of plant loop will be incorrect when applying standard.")
120
+ end
121
+
122
+ elsif chiller.referenceCapacity.is_initialized
123
+ total_cooling_capacity_w += chiller.referenceCapacity.get
124
+ elsif chiller.autosizedReferenceCapacity.is_initialized
125
+ total_cooling_capacity_w += chiller.autosizedReferenceCapacity.get
126
+ else
127
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlantLoop', "For #{plant_loop.name} capacity of #{chiller.name} is not available, total cooling capacity of plant loop will be incorrect when applying standard.")
128
+ end
129
+ # DistrictCooling
130
+ elsif sc.to_DistrictCooling.is_initialized
131
+ dist_clg = sc.to_DistrictCooling.get
132
+ if dist_clg.nominalCapacity.is_initialized
133
+ total_cooling_capacity_w += dist_clg.nominalCapacity.get
134
+ elsif dist_clg.autosizedNominalCapacity.is_initialized
135
+ total_cooling_capacity_w += dist_clg.autosizedNominalCapacity.get
136
+ else
137
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.PlantLoop', "For #{plant_loop.name} capacity of DistrictCooling #{dist_clg.name} is not available, total heating capacity of plant loop will be incorrect when applying standard.")
138
+ end
139
+ end
140
+ end
141
+
142
+ total_cooling_capacity_tons = OpenStudio.convert(total_cooling_capacity_w, 'W', 'ton').get
143
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.PlantLoop', "For #{plant_loop.name}, cooling capacity is #{total_cooling_capacity_tons.round} tons of refrigeration.")
144
+
145
+ return total_cooling_capacity_w
146
+ end
147
+
148
+ # Splits the single chiller used for the initial sizing run
149
+ # into multiple separate chillers based on Appendix G.
150
+ #
151
+ # @param plant_loop_args [Array] chilled water loop (OpenStudio::Model::PlantLoop), sizing run directory
152
+ # @return [Bool] returns true if successful, false if not
153
+ def plant_loop_apply_prm_number_of_chillers(plant_loop, sizing_run_dir = nil)
154
+ # Skip non-cooling plants & secondary cooling loop
155
+ return true unless plant_loop.sizingPlant.loopType == 'Cooling'
156
+ # If the loop is cooling but it is a secondary loop, then skip.
157
+ return true if plant_loop.additionalProperties.hasFeature('is_secondary_loop')
158
+
159
+ # Determine the number and type of chillers
160
+ num_chillers = nil
161
+ chiller_cooling_type = nil
162
+ chiller_compressor_type = nil
163
+
164
+ # Set the equipment to stage sequentially or uniformload if there is secondary loop
165
+ if plant_loop.additionalProperties.hasFeature('is_primary_loop')
166
+ plant_loop.setLoadDistributionScheme('UniformLoad')
167
+ else
168
+ plant_loop.setLoadDistributionScheme('SequentialLoad')
169
+ end
170
+
171
+ # Determine the capacity of the loop
172
+ cap_w = plant_loop_total_cooling_capacity(plant_loop, sizing_run_dir)
173
+ cap_tons = OpenStudio.convert(cap_w, 'W', 'ton').get
174
+ if cap_tons <= 300
175
+ num_chillers = 1
176
+ chiller_cooling_type = 'WaterCooled'
177
+ chiller_compressor_type = 'Rotary Screw and Scroll'
178
+ elsif cap_tons > 300 && cap_tons < 600
179
+ num_chillers = 2
180
+ chiller_cooling_type = 'WaterCooled'
181
+ chiller_compressor_type = 'Rotary Screw and Scroll'
182
+ else
183
+ # Max capacity of a single chiller
184
+ max_cap_ton = 800.0
185
+ num_chillers = (cap_tons / max_cap_ton).floor + 1
186
+ # Must be at least 2 chillers
187
+ num_chillers += 1 if num_chillers == 1
188
+ chiller_cooling_type = 'WaterCooled'
189
+ chiller_compressor_type = 'Centrifugal'
190
+ end
191
+
192
+ # Get all existing chillers and pumps
193
+ chillers = []
194
+ pumps = []
195
+ plant_loop.supplyComponents.each do |sc|
196
+ if sc.to_ChillerElectricEIR.is_initialized
197
+ chillers << sc.to_ChillerElectricEIR.get
198
+ elsif sc.to_PumpConstantSpeed.is_initialized
199
+ pumps << sc.to_PumpConstantSpeed.get
200
+ elsif sc.to_PumpVariableSpeed.is_initialized
201
+ pumps << sc.to_PumpVariableSpeed.get
202
+ end
203
+ end
204
+
205
+ # Ensure there is only 1 chiller to start
206
+ first_chiller = nil
207
+ return true if chillers.size.zero?
208
+
209
+ if chillers.size > 1
210
+ OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, found #{chillers.size} chillers, cannot split up per performance rating method baseline requirements.")
211
+ else
212
+ first_chiller = chillers[0]
213
+ end
214
+
215
+ # Ensure there is only 1 pump to start
216
+ orig_pump = nil
217
+ if pumps.size.zero?
218
+ OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, found #{pumps.size} pumps. A loop must have at least one pump.")
219
+ return false
220
+ elsif pumps.size > 1
221
+ OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, found #{pumps.size} pumps, cannot split up per performance rating method baseline requirements.")
222
+ return false
223
+ else
224
+ orig_pump = pumps[0]
225
+ end
226
+
227
+ # Determine the per-chiller capacity
228
+ # and sizing factor
229
+ per_chiller_sizing_factor = (1.0 / num_chillers).round(2)
230
+ # This is unused
231
+ per_chiller_cap_tons = cap_tons / num_chillers
232
+ per_chiller_cap_w = cap_w / num_chillers
233
+
234
+ # Set the sizing factor and the chiller type: could do it on the first chiller before cloning it, but renaming warrants looping on chillers anyways
235
+
236
+ # Add any new chillers
237
+ final_chillers = [first_chiller]
238
+ (num_chillers - 1).times do
239
+ new_chiller = first_chiller.clone(plant_loop.model)
240
+ if new_chiller.to_ChillerElectricEIR.is_initialized
241
+ new_chiller = new_chiller.to_ChillerElectricEIR.get
242
+ else
243
+ OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, could not clone chiller #{first_chiller.name}, cannot apply the performance rating method number of chillers.")
244
+ return false
245
+ end
246
+ # Connect the new chiller to the same CHW loop
247
+ # as the old chiller.
248
+ plant_loop.addSupplyBranchForComponent(new_chiller)
249
+ # Connect the new chiller to the same CW loop
250
+ # as the old chiller, if it was water-cooled.
251
+ cw_loop = first_chiller.secondaryPlantLoop
252
+ if cw_loop.is_initialized
253
+ cw_loop.get.addDemandBranchForComponent(new_chiller)
254
+ end
255
+
256
+ final_chillers << new_chiller
257
+ end
258
+
259
+ # If there is more than one cooling tower,
260
+ # add one pump to each chiller, assume chillers are equally sized
261
+ if final_chillers.size > 1
262
+ num_pumps = final_chillers.size
263
+ final_chillers.each do |chiller|
264
+ if orig_pump.to_PumpConstantSpeed.is_initialized
265
+ new_pump = OpenStudio::Model::PumpConstantSpeed.new(plant_loop.model)
266
+ new_pump.setName("#{chiller.name} Primary Pump")
267
+ # Will need to adjust the pump power after a sizing run
268
+ new_pump.setRatedPumpHead(orig_pump.ratedPumpHead / num_pumps)
269
+ new_pump.setMotorEfficiency(0.9)
270
+ new_pump.setPumpControlType('Intermittent')
271
+ chiller_inlet_node = chiller.connectedObject(chiller.supplyInletPort).get.to_Node.get
272
+ new_pump.addToNode(chiller_inlet_node)
273
+ elsif orig_pump.to_PumpVariableSpeed.is_initialized
274
+ new_pump = OpenStudio::Model::PumpVariableSpeed.new(plant_loop.model)
275
+ new_pump.setName("#{chiller.name} Primary Pump")
276
+ new_pump.setRatedPumpHead(orig_pump.ratedPumpHead / num_pumps)
277
+ new_pump.setCoefficient1ofthePartLoadPerformanceCurve(orig_pump.coefficient1ofthePartLoadPerformanceCurve)
278
+ new_pump.setCoefficient2ofthePartLoadPerformanceCurve(orig_pump.coefficient2ofthePartLoadPerformanceCurve)
279
+ new_pump.setCoefficient3ofthePartLoadPerformanceCurve(orig_pump.coefficient3ofthePartLoadPerformanceCurve)
280
+ new_pump.setCoefficient4ofthePartLoadPerformanceCurve(orig_pump.coefficient4ofthePartLoadPerformanceCurve)
281
+ chiller_inlet_node = chiller.connectedObject(chiller.supplyInletPort).get.to_Node.get
282
+ new_pump.addToNode(chiller_inlet_node)
283
+ end
284
+ end
285
+ # Remove the old pump
286
+ orig_pump.remove
287
+ end
288
+
289
+ # Set the sizing factor and the chiller types
290
+ final_chillers.each_with_index do |final_chiller, i|
291
+ final_chiller.setName("#{template} #{chiller_cooling_type} #{chiller_compressor_type} Chiller #{i + 1} of #{final_chillers.size}")
292
+ final_chiller.setSizingFactor(per_chiller_sizing_factor)
293
+ final_chiller.setReferenceCapacity(per_chiller_cap_w)
294
+ final_chiller.setCondenserType(chiller_cooling_type)
295
+ final_chiller.additionalProperties.setFeature('compressor_type', chiller_compressor_type)
296
+ end
297
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.PlantLoop', "For #{plant_loop.name}, there are #{final_chillers.size} #{chiller_cooling_type} #{chiller_compressor_type} chillers.")
298
+
299
+ return true
300
+ end
301
+
302
+ # Apply prm baseline pump power
303
+ # @note I think it makes more sense to sense the motor efficiency right there...
304
+ # But actually it's completely irrelevant...
305
+ # you could set at 0.9 and just calculate the pressure rise to have your 19 W/GPM or whatever
306
+ #
307
+ # @param plant_loop [OpenStudio::Model::PlantLoop] plant loop
308
+ # @return [Bool] returns true if successful, false if not
309
+ def plant_loop_apply_prm_baseline_pump_power(plant_loop)
310
+ hot_water_pump_power = 19 # W/gpm
311
+ hot_water_district_pump_power = 14 # W/gpm
312
+ chilled_water_primary_pump_power = 9 # W/gpm
313
+ chilled_water_secondary_pump_power = 13 # W/gpm
314
+ chilled_water_district_pump_power = 16 # W/gpm
315
+ condenser_water_pump_power = 19 # W/gpm
316
+ # Determine the pumping power per
317
+ # flow based on loop type.
318
+ w_per_gpm = nil
319
+ chiller_counter = 0
320
+
321
+ sizing_plant = plant_loop.sizingPlant
322
+ loop_type = sizing_plant.loopType
323
+
324
+ case loop_type
325
+ when 'Heating'
326
+
327
+ has_district_heating = false
328
+ plant_loop.supplyComponents.each do |sc|
329
+ if sc.to_DistrictHeating.is_initialized
330
+ has_district_heating = true
331
+ end
332
+ end
333
+
334
+ w_per_gpm = if has_district_heating # District HW
335
+ hot_water_district_pump_power
336
+ else # HW
337
+ hot_water_pump_power
338
+ end
339
+
340
+ when 'Cooling'
341
+ has_district_cooling = false
342
+ plant_loop.supplyComponents.each do |sc|
343
+ if sc.to_DistrictCooling.is_initialized
344
+ has_district_cooling = true
345
+ elsif sc.to_ChillerElectricEIR.is_initialized
346
+ chiller_counter += 1
347
+ end
348
+ end
349
+
350
+ if has_district_cooling # District CHW
351
+ w_per_gpm = chilled_water_district_pump_power
352
+ elsif plant_loop.additionalProperties.hasFeature('is_primary_loop') # The primary loop of the primary/secondary CHW
353
+ w_per_gpm = chilled_water_primary_pump_power
354
+ elsif plant_loop.additionalProperties.hasFeature('is_secondary_loop') # The secondary loop of the primary/secondary CHW
355
+ w_per_gpm = chilled_water_secondary_pump_power
356
+ else # Primary only CHW combine 9W/gpm + 13W/gpm
357
+ w_per_gpm = chilled_water_primary_pump_power + chilled_water_secondary_pump_power
358
+ end
359
+
360
+ when 'Condenser'
361
+ # @todo prm condenser loop pump power
362
+ w_per_gpm = condenser_water_pump_power
363
+ end
364
+
365
+ # Modify all the primary pumps
366
+ plant_loop.supplyComponents.each do |sc|
367
+ if sc.to_PumpConstantSpeed.is_initialized
368
+ pump = sc.to_PumpConstantSpeed.get
369
+ if chiller_counter > 0
370
+ w_per_gpm /= chiller_counter
371
+ end
372
+ pump_apply_prm_pressure_rise_and_motor_efficiency(pump, w_per_gpm)
373
+ elsif sc.to_PumpVariableSpeed.is_initialized
374
+ pump = sc.to_PumpVariableSpeed.get
375
+ pump_apply_prm_pressure_rise_and_motor_efficiency(pump, w_per_gpm)
376
+ elsif sc.to_HeaderedPumpsConstantSpeed.is_initialized
377
+ pump = sc.to_HeaderedPumpsConstantSpeed.get
378
+ pump_apply_prm_pressure_rise_and_motor_efficiency(pump, w_per_gpm)
379
+ elsif sc.to_HeaderedPumpsVariableSpeed.is_initialized
380
+ pump = sc.to_HeaderedPumpsVariableSpeed.get
381
+ pump_apply_prm_pressure_rise_and_motor_efficiency(pump, w_per_gpm)
382
+ end
383
+ end
384
+ return true
385
+ end
386
+
387
+ # Apply sizing and controls to chilled water loop
388
+ #
389
+ # @param model [OpenStudio::Model::Model] OpenStudio model object
390
+ # @param chilled_water_loop [OpenStudio::Model::PlantLoop] chilled water loop
391
+ # @param dsgn_sup_wtr_temp [Double] design chilled water supply T
392
+ # @param dsgn_sup_wtr_temp_delt [Double] design chilled water supply delta T
393
+ # @return [Bool] returns true if successful, false if not
394
+ def chw_sizing_control(model, chilled_water_loop, dsgn_sup_wtr_temp, dsgn_sup_wtr_temp_delt)
395
+
396
+ design_chilled_water_temperature = 44 # Loop design chilled water temperature (F)
397
+ design_chilled_water_temperature_delta = 10.1 # Loop design chilled water temperature (deltaF)
398
+ chw_outdoor_temperature_high = 80 # Chilled water temperature reset at high outdoor air temperature (F)
399
+ chw_outdoor_temperature_low = 60 # Chilled water temperature reset at low outdoor air temperature (F)
400
+ chw_outdoor_high_setpoint = 44 # Chilled water setpoint temperature at high outdoor air temperature (F)
401
+ chw_outdoor_low_setpoint = 54 # Chilled water setpoint temperature at low outdoor air temperature (F)
402
+ chiller_chw_low_temp_limit = 36 # Chiller leaving chilled water lower temperature limit (F)
403
+ chiller_chw_cond_temp = 95 # Chiller entering condenser fluid temperature (F)
404
+ primary_pump_power = 9 # primary pump power (W/gpm)
405
+
406
+ if dsgn_sup_wtr_temp.nil?
407
+ dsgn_sup_wtr_temp_c = OpenStudio.convert(design_chilled_water_temperature, 'F', 'C').get
408
+ else
409
+ dsgn_sup_wtr_temp_c = OpenStudio.convert(dsgn_sup_wtr_temp, 'F', 'C').get
410
+ end
411
+ if dsgn_sup_wtr_temp_delt.nil?
412
+ dsgn_sup_wtr_temp_delt_k = OpenStudio.convert(design_chilled_water_temperature_delta, 'R', 'K').get
413
+ else
414
+ dsgn_sup_wtr_temp_delt_k = OpenStudio.convert(dsgn_sup_wtr_temp_delt, 'R', 'K').get
415
+ end
416
+ chilled_water_loop.setMinimumLoopTemperature(1.0)
417
+ chilled_water_loop.setMaximumLoopTemperature(40.0)
418
+
419
+ sizing_plant = chilled_water_loop.sizingPlant
420
+ sizing_plant.setLoopType('Cooling')
421
+ sizing_plant.setDesignLoopExitTemperature(dsgn_sup_wtr_temp_c)
422
+ sizing_plant.setLoopDesignTemperatureDifference(dsgn_sup_wtr_temp_delt_k)
423
+ # Use OA reset setpoint manager
424
+ outdoor_low_temperature_C = OpenStudio.convert(chw_outdoor_temperature_low, 'F', 'C').get.round(1)
425
+ outdoor_high_temperature_C = OpenStudio.convert(chw_outdoor_temperature_high, 'F', 'C').get.round(1)
426
+ setpoint_temperature_outdoor_high_C = OpenStudio.convert(chw_outdoor_high_setpoint, 'F', 'C').get.round(1)
427
+ setpoint_temperature_outdoor_low_C = OpenStudio.convert(chw_outdoor_low_setpoint, 'F', 'C').get.round(1)
428
+
429
+ chw_stpt_manager = OpenStudio::Model::SetpointManagerOutdoorAirReset.new(model)
430
+ chw_stpt_manager.setName("#{chilled_water_loop.name} Setpoint Manager")
431
+ chw_stpt_manager.setOutdoorHighTemperature(outdoor_high_temperature_C) # Degrees Celsius
432
+ chw_stpt_manager.setSetpointatOutdoorHighTemperature(setpoint_temperature_outdoor_high_C) # Degrees Celsius
433
+ chw_stpt_manager.setOutdoorLowTemperature(outdoor_low_temperature_C) # Degrees Celsius
434
+ chw_stpt_manager.setSetpointatOutdoorLowTemperature(setpoint_temperature_outdoor_low_C) # Degrees Celsius
435
+ chw_stpt_manager.addToNode(chilled_water_loop.supplyOutletNode)
436
+
437
+ return true
438
+ end
439
+
440
+ # Set configuration in model for chilled water primary/secondary loop interface
441
+ # Use heat_exchanger for stable baseline
442
+ #
443
+ # @param model [OpenStudio::Model::Model] OpenStudio model object
444
+ # @return [String] common_pipe or heat_exchanger
445
+ def plant_loop_set_chw_pri_sec_configuration(model)
446
+ pri_sec_config = 'heat_exchanger'
447
+ return pri_sec_config
448
+ end
449
+
450
+ end