urbanopt-cli 0.4.1 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (944) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/CHANGELOG.md +59 -0
  4. data/CMakeLists.txt +17 -17
  5. data/FindOpenStudioSDK.cmake +12 -7
  6. data/Gemfile +8 -10
  7. data/LICENSE.md +11 -1
  8. data/README.md +1 -0
  9. data/Rakefile +16 -6
  10. data/example_files/Gemfile +25 -9
  11. data/example_files/example_project.json +35 -20
  12. data/example_files/example_project_combined.json +100 -5
  13. data/example_files/example_project_with_electric_network.json +2116 -0
  14. data/example_files/mappers/Baseline.rb +111 -51
  15. data/example_files/mappers/CreateBar.rb +19 -7
  16. data/example_files/mappers/EvCharging.rb +141 -0
  17. data/example_files/mappers/Floorspace.rb +29 -17
  18. data/example_files/mappers/HighEfficiency.rb +20 -8
  19. data/example_files/mappers/HighEfficiencyCreateBar.rb +19 -8
  20. data/example_files/mappers/HighEfficiencyFloorspace.rb +19 -8
  21. data/example_files/mappers/ThermalStorage.rb +16 -6
  22. data/example_files/mappers/base_workflow.osw +26 -1
  23. data/example_files/mappers/floorspace_workflow.osw +9 -0
  24. data/example_files/measures/BuildResidentialModel/measure.rb +249 -134
  25. data/example_files/reopt/base_assumptions.json +2 -2
  26. data/example_files/reopt/multiPV_assumptions.json +4 -3
  27. data/example_files/residential/clothes_dryer.tsv +7 -7
  28. data/example_files/residential/clothes_washer.tsv +2 -2
  29. data/example_files/residential/cooling_system.tsv +42 -22
  30. data/example_files/residential/dishwasher.tsv +1 -1
  31. data/example_files/residential/exhaust.tsv +3 -0
  32. data/example_files/residential/heat_pump.tsv +62 -40
  33. data/example_files/residential/water_heater.tsv +1 -1
  34. data/example_files/resources/hpxml-measures/.github/pull_request_template.md +14 -0
  35. data/example_files/resources/hpxml-measures/.github/workflows/config.yml +116 -0
  36. data/example_files/resources/hpxml-measures/.gitignore +1 -8
  37. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/measure.rb +1088 -1329
  38. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/measure.xml +1819 -1383
  39. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/resources/constants.rb +0 -8
  40. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/resources/geometry.rb +450 -362
  41. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/resources/schedules.rb +165 -112
  42. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/resources/schedules_config.json +388 -0
  43. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/resources/schedules_config.md +43 -0
  44. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/resources/schedules_weekday_state_and_monthly_schedule_shift.csv +613 -0
  45. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/resources/schedules_weekend_state_and_monthly_schedule_shift.csv +613 -0
  46. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-appliances-coal.osw +56 -82
  47. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{base-appliances-dehumidifier-ief.osw → base-appliances-dehumidifier-ief-portable.osw} +57 -83
  48. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{base-appliances-dehumidifier-50percent.osw → base-appliances-dehumidifier-ief-whole-home.osw} +59 -85
  49. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-appliances-dehumidifier.osw +56 -82
  50. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-appliances-gas.osw +56 -82
  51. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-appliances-modified.osw +56 -82
  52. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-appliances-none.osw +61 -87
  53. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-appliances-oil.osw +56 -82
  54. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-appliances-propane.osw +56 -82
  55. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-appliances-wood.osw +56 -82
  56. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-atticroof-flat.osw +56 -82
  57. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-atticroof-radiant-barrier.osw +56 -82
  58. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-atticroof-unvented-insulated-roof.osw +56 -82
  59. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-atticroof-vented.osw +56 -82
  60. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-bldgtype-multifamily-shared-boiler-only-baseboard.osw +341 -0
  61. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-bldgtype-multifamily-shared-boiler-only-fan-coil.osw +341 -0
  62. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{extra-mechvent-shared-preconditioning.osw → base-bldgtype-multifamily-shared-mechvent-preconditioning.osw} +70 -95
  63. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{extra-mechvent-shared.osw → base-bldgtype-multifamily-shared-mechvent.osw} +70 -95
  64. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-bldgtype-multifamily-shared-pv.osw +341 -0
  65. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-bldgtype-multifamily-shared-water-heater.osw +341 -0
  66. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-bldgtype-multifamily.osw +341 -0
  67. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{base-single-family-attached.osw → base-bldgtype-single-family-attached.osw} +59 -85
  68. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-combi-tankless-outside.osw +56 -82
  69. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-combi-tankless.osw +56 -82
  70. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-dwhr.osw +56 -82
  71. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-indirect-outside.osw +56 -82
  72. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-indirect-standbyloss.osw +56 -82
  73. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-indirect-with-solar-fraction.osw +56 -82
  74. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-indirect.osw +56 -82
  75. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-jacket-electric.osw +56 -82
  76. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-jacket-gas.osw +56 -82
  77. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-jacket-hpwh.osw +56 -82
  78. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-jacket-indirect.osw +56 -82
  79. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-low-flow-fixtures.osw +56 -82
  80. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-none.osw +57 -83
  81. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-recirc-demand.osw +56 -82
  82. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-recirc-manual.osw +56 -82
  83. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-recirc-nocontrol.osw +56 -82
  84. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-recirc-temperature.osw +56 -82
  85. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-recirc-timer.osw +56 -82
  86. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-solar-direct-evacuated-tube.osw +56 -82
  87. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-solar-direct-flat-plate.osw +56 -82
  88. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-solar-direct-ics.osw +56 -82
  89. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-solar-fraction.osw +56 -82
  90. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-solar-indirect-flat-plate.osw +56 -82
  91. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-solar-thermosyphon-flat-plate.osw +56 -82
  92. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tank-coal.osw +56 -82
  93. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tank-elec-uef.osw +338 -0
  94. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tank-gas-outside.osw +56 -82
  95. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tank-gas-uef.osw +338 -0
  96. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tank-gas.osw +56 -82
  97. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tank-heat-pump-outside.osw +56 -82
  98. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tank-heat-pump-uef.osw +338 -0
  99. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tank-heat-pump-with-solar-fraction.osw +56 -82
  100. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tank-heat-pump-with-solar.osw +56 -82
  101. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tank-heat-pump.osw +56 -82
  102. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tank-oil.osw +56 -82
  103. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tank-wood.osw +56 -82
  104. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tankless-electric-outside.osw +56 -83
  105. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tankless-electric-uef.osw +337 -0
  106. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tankless-electric.osw +56 -82
  107. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tankless-gas-uef.osw +337 -0
  108. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tankless-gas-with-solar-fraction.osw +56 -82
  109. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tankless-gas-with-solar.osw +56 -82
  110. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tankless-gas.osw +56 -82
  111. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-dhw-tankless-propane.osw +56 -82
  112. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-2stories-garage.osw +56 -82
  113. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-2stories.osw +56 -82
  114. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-beds-1.osw +56 -82
  115. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-beds-2.osw +56 -82
  116. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-beds-4.osw +56 -82
  117. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-beds-5.osw +56 -82
  118. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-garage.osw +56 -82
  119. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-infil-ach-house-pressure.osw +56 -82
  120. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-infil-cfm-house-pressure.osw +56 -82
  121. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-infil-cfm50.osw +56 -82
  122. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-infil-flue.osw +56 -82
  123. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-infil-natural-ach.osw +57 -83
  124. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-overhangs.osw +57 -83
  125. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-enclosure-windows-none.osw +56 -82
  126. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-foundation-ambient.osw +56 -82
  127. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-foundation-conditioned-basement-slab-insulation.osw +56 -82
  128. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-foundation-slab.osw +56 -82
  129. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-foundation-unconditioned-basement-assembly-r.osw +55 -81
  130. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-foundation-unconditioned-basement-wall-insulation.osw +55 -81
  131. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-foundation-unconditioned-basement.osw +55 -81
  132. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-foundation-unvented-crawlspace.osw +55 -81
  133. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-foundation-vented-crawlspace.osw +55 -81
  134. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-air-to-air-heat-pump-1-speed-cooling-only.osw +337 -0
  135. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-air-to-air-heat-pump-1-speed-heating-only.osw +337 -0
  136. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-air-to-air-heat-pump-1-speed.osw +56 -82
  137. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-air-to-air-heat-pump-2-speed.osw +56 -82
  138. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-air-to-air-heat-pump-var-speed.osw +56 -82
  139. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-boiler-coal-only.osw +56 -82
  140. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-boiler-elec-only.osw +56 -82
  141. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-boiler-gas-central-ac-1-speed.osw +56 -82
  142. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-boiler-gas-only.osw +56 -82
  143. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-boiler-oil-only.osw +56 -82
  144. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-boiler-propane-only.osw +56 -82
  145. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-boiler-wood-only.osw +56 -82
  146. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-central-ac-only-1-speed.osw +56 -82
  147. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-central-ac-only-2-speed.osw +56 -82
  148. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-central-ac-only-var-speed.osw +56 -82
  149. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-central-ac-plus-air-to-air-heat-pump-heating.osw +56 -82
  150. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-dual-fuel-air-to-air-heat-pump-1-speed-electric.osw +55 -81
  151. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-dual-fuel-air-to-air-heat-pump-1-speed.osw +55 -81
  152. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-dual-fuel-air-to-air-heat-pump-2-speed.osw +55 -81
  153. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-dual-fuel-air-to-air-heat-pump-var-speed.osw +55 -81
  154. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-dual-fuel-mini-split-heat-pump-ducted.osw +56 -82
  155. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-ducts-leakage-percent.osw +56 -82
  156. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-elec-resistance-only.osw +56 -82
  157. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-evap-cooler-furnace-gas.osw +56 -82
  158. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-evap-cooler-only-ducted.osw +57 -83
  159. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-evap-cooler-only.osw +56 -82
  160. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-fireplace-wood-only.osw +56 -82
  161. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-fixed-heater-gas-only.osw +57 -83
  162. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-floor-furnace-propane-only.osw +56 -82
  163. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-furnace-coal-only.osw +337 -0
  164. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-furnace-elec-central-ac-1-speed.osw +56 -82
  165. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-furnace-elec-only.osw +56 -82
  166. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-furnace-gas-central-ac-2-speed.osw +56 -82
  167. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-furnace-gas-central-ac-var-speed.osw +56 -82
  168. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-furnace-gas-only.osw +56 -82
  169. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-furnace-gas-room-ac.osw +56 -82
  170. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-furnace-oil-only.osw +56 -82
  171. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-furnace-propane-only.osw +56 -82
  172. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-furnace-wood-only.osw +56 -82
  173. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-ground-to-air-heat-pump-cooling-only.osw +336 -0
  174. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-ground-to-air-heat-pump-heating-only.osw +336 -0
  175. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-ground-to-air-heat-pump.osw +56 -84
  176. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-airflow-defect-furnace-gas-central-ac-1-speed.osw +339 -0
  177. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-all-air-to-air-heat-pump-1-speed.osw +339 -0
  178. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-all-air-to-air-heat-pump-2-speed.osw +339 -0
  179. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-all-air-to-air-heat-pump-var-speed.osw +339 -0
  180. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-all-furnace-gas-central-ac-1-speed.osw +340 -0
  181. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-all-furnace-gas-central-ac-2-speed.osw +340 -0
  182. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-all-furnace-gas-central-ac-var-speed.osw +340 -0
  183. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-all-furnace-gas-only.osw +338 -0
  184. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-all-ground-to-air-heat-pump.osw +338 -0
  185. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-all-mini-split-air-conditioner-only-ducted.osw +338 -0
  186. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-all-mini-split-heat-pump-ducted.osw +339 -0
  187. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-charge-defect-furnace-gas-central-ac-1-speed.osw +338 -0
  188. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-install-quality-none-furnace-gas-central-ac-1-speed.osw +340 -0
  189. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-mini-split-air-conditioner-only-ducted.osw +56 -82
  190. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-mini-split-air-conditioner-only-ductless.osw +56 -82
  191. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-mini-split-heat-pump-ducted-cooling-only.osw +56 -82
  192. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-mini-split-heat-pump-ducted-heating-only.osw +56 -82
  193. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-mini-split-heat-pump-ducted.osw +57 -83
  194. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-mini-split-heat-pump-ductless.osw +57 -83
  195. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-none.osw +56 -82
  196. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-portable-heater-gas-only.osw +57 -83
  197. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-programmable-thermostat-detailed.osw +337 -0
  198. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-room-ac-only-33percent.osw +56 -82
  199. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-room-ac-only.osw +56 -82
  200. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-setpoints.osw +56 -82
  201. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-stove-oil-only.osw +56 -82
  202. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-stove-wood-pellets-only.osw +56 -82
  203. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-undersized.osw +56 -82
  204. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-hvac-wall-furnace-elec-only.osw +56 -82
  205. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-lighting-ceiling-fans.osw +57 -83
  206. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-lighting-detailed.osw +56 -82
  207. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-location-AMY-2012.osw +56 -82
  208. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-location-baltimore-md.osw +64 -90
  209. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-location-dallas-tx.osw +56 -82
  210. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-location-duluth-mn.osw +69 -95
  211. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-location-helena-mt.osw +337 -0
  212. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-location-honolulu-hi.osw +337 -0
  213. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-location-miami-fl.osw +56 -82
  214. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-location-phoenix-az.osw +337 -0
  215. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-location-portland-or.osw +337 -0
  216. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-mechvent-balanced.osw +56 -82
  217. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-mechvent-bath-kitchen-fans.osw +64 -92
  218. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-mechvent-cfis-evap-cooler-only-ducted.osw +57 -83
  219. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-mechvent-cfis.osw +56 -82
  220. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-mechvent-erv-atre-asre.osw +56 -82
  221. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-mechvent-erv.osw +56 -82
  222. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-mechvent-exhaust-rated-flow-rate.osw +337 -0
  223. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-mechvent-exhaust.osw +56 -82
  224. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-mechvent-hrv-asre.osw +56 -82
  225. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-mechvent-hrv.osw +56 -82
  226. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-mechvent-supply.osw +56 -82
  227. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-mechvent-whole-house-fan.osw +56 -82
  228. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-misc-defaults.osw +57 -83
  229. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-misc-loads-large-uncommon.osw +60 -86
  230. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-misc-loads-large-uncommon2.osw +60 -86
  231. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-misc-neighbor-shading.osw +56 -82
  232. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-misc-shielding-of-home.osw +337 -0
  233. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-misc-usage-multiplier.osw +52 -78
  234. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-pv.osw +52 -78
  235. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{extra-vacancy-6-months.osw → base-schedules-stochastic-vacant.osw} +59 -85
  236. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-schedules-stochastic.osw +56 -82
  237. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-schedules-user-specified.osw +56 -82
  238. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-simcontrol-calendar-year-custom.osw +56 -82
  239. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-simcontrol-daylight-saving-custom.osw +56 -82
  240. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-simcontrol-daylight-saving-disabled.osw +56 -82
  241. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-simcontrol-runperiod-1-month.osw +56 -82
  242. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base-simcontrol-timestep-10-mins.osw +56 -82
  243. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/base.osw +56 -82
  244. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/build_residential_hpxml_test.rb +71 -57
  245. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-auto.osw +56 -82
  246. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-double-exterior.osw +341 -0
  247. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-double-loaded-interior.osw +341 -0
  248. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-eaves.osw +341 -0
  249. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-single-exterior-front.osw +341 -0
  250. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-double-loaded-interior.osw +341 -0
  251. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-left-bottom-double-loaded-interior.osw +341 -0
  252. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-left-bottom.osw +341 -0
  253. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-left-middle-double-loaded-interior.osw +341 -0
  254. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-left-middle.osw +341 -0
  255. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-left-top-double-loaded-interior.osw +341 -0
  256. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-left-top.osw +341 -0
  257. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-middle-bottom-double-loaded-interior.osw +341 -0
  258. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-middle-bottom.osw +341 -0
  259. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-middle-middle-double-loaded-interior.osw +341 -0
  260. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-middle-middle.osw +341 -0
  261. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-middle-top-double-loaded-interior.osw +341 -0
  262. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-middle-top.osw +341 -0
  263. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-right-bottom-double-loaded-interior.osw +341 -0
  264. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-right-bottom.osw +341 -0
  265. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-right-middle-double-loaded-interior.osw +341 -0
  266. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-right-middle.osw +341 -0
  267. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-right-top-double-loaded-interior.osw +341 -0
  268. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab-right-top.osw +341 -0
  269. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-slab.osw +341 -0
  270. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-double-loaded-interior.osw +341 -0
  271. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-left-bottom-double-loaded-interior.osw +341 -0
  272. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-left-bottom.osw +341 -0
  273. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-left-middle-double-loaded-interior.osw +341 -0
  274. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-left-middle.osw +341 -0
  275. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-left-top-double-loaded-interior.osw +341 -0
  276. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-left-top.osw +341 -0
  277. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-middle-bottom-double-loaded-interior.osw +341 -0
  278. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-middle-bottom.osw +341 -0
  279. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-middle-middle-double-loaded-interior.osw +341 -0
  280. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-middle-middle.osw +341 -0
  281. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-middle-top-double-loaded-interior.osw +341 -0
  282. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-middle-top.osw +341 -0
  283. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-right-bottom-double-loaded-interior.osw +341 -0
  284. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-right-bottom.osw +341 -0
  285. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-right-middle-double-loaded-interior.osw +341 -0
  286. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-right-middle.osw +341 -0
  287. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-right-top-double-loaded-interior.osw +341 -0
  288. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace-right-top.osw +341 -0
  289. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-unvented-crawlspace.osw +341 -0
  290. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-double-loaded-interior.osw +341 -0
  291. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-left-bottom-double-loaded-interior.osw +341 -0
  292. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-left-bottom.osw +341 -0
  293. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-left-middle-double-loaded-interior.osw +341 -0
  294. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-left-middle.osw +341 -0
  295. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-left-top-double-loaded-interior.osw +341 -0
  296. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-left-top.osw +341 -0
  297. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-middle-bottom-double-loaded-interior.osw +341 -0
  298. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-middle-bottom.osw +341 -0
  299. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-middle-middle-double-loaded-interior.osw +341 -0
  300. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-middle-middle.osw +341 -0
  301. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-middle-top-double-loaded-interior.osw +341 -0
  302. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-middle-top.osw +341 -0
  303. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-right-bottom-double-loaded-interior.osw +341 -0
  304. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-right-bottom.osw +341 -0
  305. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-right-middle-double-loaded-interior.osw +341 -0
  306. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-right-middle.osw +341 -0
  307. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-right-top-double-loaded-interior.osw +341 -0
  308. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace-right-top.osw +341 -0
  309. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-multifamily-vented-crawlspace.osw +341 -0
  310. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-atticroof-conditioned-eaves-gable.osw +339 -0
  311. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-atticroof-conditioned-eaves-hip.osw +339 -0
  312. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-atticroof-flat.osw +339 -0
  313. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{extra-pv-shared.osw → extra-bldgtype-single-family-attached-double-exterior.osw} +62 -89
  314. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-double-loaded-interior.osw +339 -0
  315. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{extra-dhw-shared-water-heater.osw → extra-bldgtype-single-family-attached-single-exterior-front.osw} +60 -86
  316. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-slab-middle.osw +339 -0
  317. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-slab-right.osw +339 -0
  318. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-slab.osw +339 -0
  319. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-unconditioned-basement-middle.osw +339 -0
  320. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-unconditioned-basement-right.osw +339 -0
  321. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{base-multifamily.osw → extra-bldgtype-single-family-attached-unconditioned-basement.osw} +64 -91
  322. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-unvented-crawlspace-middle.osw +339 -0
  323. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-unvented-crawlspace-right.osw +339 -0
  324. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-unvented-crawlspace.osw +339 -0
  325. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-vented-crawlspace-middle.osw +339 -0
  326. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-vented-crawlspace-right.osw +339 -0
  327. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-bldgtype-single-family-attached-vented-crawlspace.osw +339 -0
  328. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-dhw-solar-latitude.osw +56 -82
  329. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-enclosure-atticroof-conditioned-eaves-gable.osw +337 -0
  330. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-enclosure-atticroof-conditioned-eaves-hip.osw +337 -0
  331. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-enclosure-garage-atticroof-conditioned.osw +337 -0
  332. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-enclosure-garage-partially-protruded.osw +56 -82
  333. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-enclosure-windows-shading.osw +339 -0
  334. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-gas-hot-tub-heater-with-zero-kwh.osw +337 -0
  335. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-gas-pool-heater-with-zero-kwh.osw +337 -0
  336. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-pv-roofpitch.osw +56 -82
  337. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-schedules-random-seed.osw +338 -0
  338. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-second-heating-system-boiler-to-heat-pump.osw +336 -0
  339. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-second-heating-system-boiler-to-heating-system.osw +337 -0
  340. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-second-heating-system-fireplace-to-heat-pump.osw +337 -0
  341. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{extra-second-heating-system-fireplace.osw → extra-second-heating-system-fireplace-to-heating-system.osw} +58 -84
  342. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-second-heating-system-portable-heater-to-heat-pump.osw +337 -0
  343. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{extra-second-heating-system-portable-heater.osw → extra-second-heating-system-portable-heater-to-heating-system.osw} +56 -82
  344. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-second-refrigerator.osw +56 -82
  345. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-zero-clothes-washer-kwh.osw +337 -0
  346. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-zero-dishwasher-kwh.osw +337 -0
  347. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-zero-extra-refrigerator-kwh.osw +337 -0
  348. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-zero-freezer-kwh.osw +337 -0
  349. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/extra-zero-refrigerator-kwh.osw +337 -0
  350. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/conditioned-attic-with-floor-insulation.osw +59 -85
  351. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/conditioned-attic-with-one-floor-above-grade.osw +337 -0
  352. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/conditioned-basement-with-ceiling-insulation.osw +56 -82
  353. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/cooling-system-and-heat-pump.osw +56 -82
  354. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/dhw-indirect-without-boiler.osw +56 -82
  355. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/ducts-location-and-areas-not-same-type.osw +56 -82
  356. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/foundation-wall-insulation-greater-than-height.osw +337 -0
  357. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/heating-system-and-heat-pump.osw +56 -82
  358. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/multifamily-bottom-crawlspace-zero-foundation-height.osw +64 -89
  359. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/multifamily-bottom-slab-non-zero-foundation-height.osw +64 -89
  360. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/multifamily-no-building-orientation.osw +63 -88
  361. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{base-hvac-programmable-thermostat.osw → invalid_files/multipliers-without-fuel-loads.osw} +54 -80
  362. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/multipliers-without-other-plug-loads.osw +337 -0
  363. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/multipliers-without-tv-plug-loads.osw +337 -0
  364. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/{base-dhw-uef.osw → invalid_files/multipliers-without-vehicle-plug-loads.osw} +58 -84
  365. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/multipliers-without-well-pump-plug-loads.osw +337 -0
  366. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/non-electric-heat-pump-water-heater.osw +56 -82
  367. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/non-integer-ceiling-fan-quantity.osw +56 -82
  368. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/non-integer-geometry-num-bathrooms.osw +56 -82
  369. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/second-heating-system-but-no-primary-heating.osw +337 -0
  370. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/second-heating-system-serves-majority-heat.osw +56 -82
  371. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/second-heating-system-serves-total-heat-load.osw +337 -0
  372. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/single-family-attached-ambient.osw +58 -84
  373. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/single-family-attached-no-building-orientation.osw +58 -84
  374. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/single-family-detached-finished-basement-zero-foundation-height.osw +56 -82
  375. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/single-family-detached-slab-non-zero-foundation-height.osw +56 -82
  376. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/single-family-detached-with-shared-system.osw +337 -0
  377. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/slab-non-zero-foundation-height-above-grade.osw +56 -82
  378. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/unconditioned-basement-with-wall-and-ceiling-insulation.osw +56 -82
  379. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/unvented-attic-with-floor-and-roof-insulation.osw +56 -82
  380. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/unvented-crawlspace-with-wall-and-ceiling-insulation.osw +59 -85
  381. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/vented-attic-with-floor-and-roof-insulation.osw +58 -84
  382. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/vented-crawlspace-with-wall-and-ceiling-insulation.osw +56 -82
  383. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/invalid_files/zero-number-of-bedrooms.osw +337 -0
  384. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/tests/schedules/vacant.csv +8761 -0
  385. data/example_files/resources/hpxml-measures/Changelog.md +249 -0
  386. data/example_files/resources/hpxml-measures/Gemfile +2 -5
  387. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/measure.rb +404 -1357
  388. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/measure.xml +247 -171
  389. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/BaseElements.xsd +11 -101
  390. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/EPvalidator.xml +824 -301
  391. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/HPXMLDataTypes.xsd +18 -35
  392. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/HPXMLvalidator.xml +526 -0
  393. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/airflow.rb +135 -207
  394. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/constants.rb +14 -186
  395. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/constructions.rb +549 -93
  396. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/energyplus.rb +12 -15
  397. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/generator.rb +78 -0
  398. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/geometry.rb +413 -15
  399. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/hotwater_appliances.rb +48 -37
  400. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/hpxml.rb +1627 -1227
  401. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/hpxml_defaults.rb +1192 -434
  402. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/hvac.rb +1555 -1616
  403. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/hvac_sizing.rb +1436 -1479
  404. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/lighting.rb +3 -2
  405. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/location.rb +22 -10
  406. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/meta_measure.rb +85 -19
  407. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/minitest_helper.rb +4 -26
  408. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/misc_loads.rb +22 -46
  409. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/pv.rb +22 -21
  410. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/schedules.rb +51 -14
  411. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/simcontrols.rb +24 -7
  412. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/unit_conversions.rb +2 -0
  413. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/validator.rb +80 -19
  414. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/version.rb +9 -2
  415. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/waterheater.rb +106 -75
  416. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/resources/xmlhelper.rb +109 -34
  417. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_airflow.rb +22 -36
  418. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_defaults.rb +1565 -768
  419. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_enclosure.rb +151 -0
  420. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_generator.rb +101 -0
  421. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_hotwater_appliance.rb +9 -18
  422. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_hvac.rb +316 -28
  423. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_hvac_sizing.rb +53 -0
  424. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_lighting.rb +4 -2
  425. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_location.rb +13 -11
  426. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_miscloads.rb +4 -2
  427. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_pv.rb +5 -3
  428. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_simcontrols.rb +13 -11
  429. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_validation.rb +102 -62
  430. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/test_water_heater.rb +189 -35
  431. data/example_files/resources/hpxml-measures/HPXMLtoOpenStudio/tests/util.rb +26 -0
  432. data/example_files/resources/hpxml-measures/README.md +5 -5
  433. data/example_files/resources/hpxml-measures/Rakefile +2 -10
  434. data/example_files/resources/hpxml-measures/SimulationOutputReport/measure.rb +416 -299
  435. data/example_files/resources/hpxml-measures/SimulationOutputReport/measure.xml +364 -481
  436. data/example_files/resources/hpxml-measures/SimulationOutputReport/resources/constants.rb +1 -2
  437. data/example_files/resources/hpxml-measures/SimulationOutputReport/tests/output_report_test.rb +327 -320
  438. data/example_files/resources/hpxml-measures/docs/source/build_residential_hpxml.rst +3 -3
  439. data/example_files/resources/hpxml-measures/docs/source/conf.py +11 -5
  440. data/example_files/resources/hpxml-measures/docs/source/getting_started.rst +6 -6
  441. data/example_files/resources/hpxml-measures/docs/source/index.rst +2 -2
  442. data/example_files/resources/hpxml-measures/docs/source/intro.rst +7 -109
  443. data/example_files/resources/hpxml-measures/docs/source/nstatic/stylesheet.css +13 -1
  444. data/example_files/resources/hpxml-measures/docs/source/workflow_inputs.rst +2482 -0
  445. data/example_files/resources/hpxml-measures/docs/source/workflow_outputs.rst +282 -0
  446. data/example_files/resources/hpxml-measures/tasks.rb +2494 -1248
  447. data/example_files/resources/hpxml-measures/weather/USA_AZ_Phoenix-Sky.Harbor.Intl.AP.722780_TMY3-cache.csv +35 -0
  448. data/example_files/resources/hpxml-measures/weather/USA_AZ_Phoenix-Sky.Harbor.Intl.AP.722780_TMY3.epw +8768 -0
  449. data/example_files/resources/hpxml-measures/weather/USA_CO_Denver.Intl.AP.725650_TMY3-cache.csv +10 -10
  450. data/example_files/resources/hpxml-measures/weather/USA_HI_Honolulu.Intl.AP.911820_TMY3-cache.csv +35 -0
  451. data/example_files/resources/hpxml-measures/weather/USA_HI_Honolulu.Intl.AP.911820_TMY3.epw +8768 -0
  452. data/example_files/resources/hpxml-measures/weather/USA_MT_Helena.Rgnl.AP.727720_TMY3-cache.csv +35 -0
  453. data/example_files/resources/hpxml-measures/weather/USA_MT_Helena.Rgnl.AP.727720_TMY3.epw +8768 -0
  454. data/example_files/resources/hpxml-measures/weather/USA_OR_Portland.Intl.AP.726980_TMY3-cache.csv +35 -0
  455. data/example_files/resources/hpxml-measures/weather/USA_OR_Portland.Intl.AP.726980_TMY3.epw +8768 -0
  456. data/example_files/resources/hpxml-measures/workflow/run_simulation.rb +96 -21
  457. data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-coal.xml +558 -559
  458. data/example_files/resources/hpxml-measures/workflow/sample_files/{base-appliances-dehumidifier-ief.xml → base-appliances-dehumidifier-ief-portable.xml} +8 -7
  459. data/example_files/resources/hpxml-measures/workflow/sample_files/{base-appliances-dehumidifier-50percent.xml → base-appliances-dehumidifier-ief-whole-home.xml} +10 -9
  460. data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-dehumidifier-multiple.xml +535 -0
  461. data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-dehumidifier.xml +525 -524
  462. data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-gas.xml +558 -559
  463. data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-modified.xml +564 -565
  464. data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-none.xml +513 -513
  465. data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-oil.xml +558 -559
  466. data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-propane.xml +558 -559
  467. data/example_files/resources/hpxml-measures/workflow/sample_files/base-appliances-wood.xml +558 -559
  468. data/example_files/resources/hpxml-measures/workflow/sample_files/base-atticroof-cathedral.xml +565 -566
  469. data/example_files/resources/hpxml-measures/workflow/sample_files/base-atticroof-conditioned.xml +633 -634
  470. data/example_files/resources/hpxml-measures/workflow/sample_files/base-atticroof-flat.xml +531 -532
  471. data/example_files/resources/hpxml-measures/workflow/sample_files/base-atticroof-radiant-barrier.xml +517 -518
  472. data/example_files/resources/hpxml-measures/workflow/sample_files/base-atticroof-unvented-insulated-roof.xml +562 -563
  473. data/example_files/resources/hpxml-measures/workflow/sample_files/base-atticroof-vented.xml +565 -566
  474. data/example_files/resources/hpxml-measures/workflow/sample_files/{base-enclosure-other-multifamily-buffer-space.xml → base-bldgtype-multifamily-adjacent-to-multifamily-buffer-space.xml} +34 -62
  475. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-multiple.xml +554 -0
  476. data/example_files/resources/hpxml-measures/workflow/sample_files/{base-enclosure-other-non-freezing-space.xml → base-bldgtype-multifamily-adjacent-to-non-freezing-space.xml} +34 -62
  477. data/example_files/resources/hpxml-measures/workflow/sample_files/{base-enclosure-other-heated-space.xml → base-bldgtype-multifamily-adjacent-to-other-heated-space.xml} +34 -62
  478. data/example_files/resources/hpxml-measures/workflow/sample_files/{base-enclosure-other-housing-unit.xml → base-bldgtype-multifamily-adjacent-to-other-housing-unit.xml} +34 -62
  479. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-baseboard.xml +425 -0
  480. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-fan-coil-ducted.xml +457 -0
  481. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-fan-coil.xml +427 -0
  482. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-water-loop-heat-pump.xml +479 -0
  483. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-cooling-tower-water-loop-heat-pump.xml +474 -0
  484. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-baseboard.xml +408 -0
  485. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil-ducted.xml +439 -0
  486. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil-eae.xml +406 -0
  487. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil.xml +409 -0
  488. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-water-loop-heat-pump.xml +457 -0
  489. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-baseboard.xml +407 -0
  490. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-fan-coil-ducted.xml +438 -0
  491. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-fan-coil.xml +408 -0
  492. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-water-loop-heat-pump.xml +456 -0
  493. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-cooling-tower-only-water-loop-heat-pump.xml +451 -0
  494. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-generator.xml +460 -0
  495. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-ground-loop-ground-to-air-heat-pump.xml +451 -0
  496. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-laundry-room.xml +466 -0
  497. data/example_files/resources/hpxml-measures/workflow/sample_files/{base-mechvent-shared-multiple.xml → base-bldgtype-multifamily-shared-mechvent-multiple.xml} +43 -415
  498. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent-preconditioning.xml +489 -0
  499. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent.xml +473 -0
  500. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-pv.xml +465 -0
  501. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-water-heater-recirc.xml +458 -0
  502. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily-shared-water-heater.xml +451 -0
  503. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-multifamily.xml +448 -0
  504. data/example_files/resources/hpxml-measures/workflow/sample_files/base-bldgtype-single-family-attached.xml +619 -0
  505. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-combi-tankless-outside.xml +516 -519
  506. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-combi-tankless.xml +516 -519
  507. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-desuperheater-2-speed.xml +550 -551
  508. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-desuperheater-gshp.xml +7 -9
  509. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-desuperheater-hpwh.xml +563 -564
  510. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-desuperheater-tankless.xml +548 -549
  511. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-desuperheater-var-speed.xml +550 -551
  512. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-desuperheater.xml +550 -551
  513. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-dwhr.xml +567 -568
  514. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-indirect-dse.xml +517 -520
  515. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-indirect-outside.xml +517 -520
  516. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-indirect-standbyloss.xml +518 -521
  517. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-indirect-with-solar-fraction.xml +525 -528
  518. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-indirect.xml +517 -520
  519. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-jacket-electric.xml +567 -568
  520. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-jacket-gas.xml +568 -569
  521. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-jacket-hpwh.xml +566 -567
  522. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-jacket-indirect.xml +522 -525
  523. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-low-flow-fixtures.xml +562 -563
  524. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-multiple.xml +575 -578
  525. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-none.xml +497 -497
  526. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-recirc-demand.xml +565 -566
  527. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-recirc-manual.xml +565 -566
  528. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-recirc-nocontrol.xml +565 -566
  529. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-recirc-temperature.xml +565 -566
  530. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-recirc-timer.xml +565 -566
  531. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-solar-direct-evacuated-tube.xml +577 -578
  532. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-solar-direct-flat-plate.xml +577 -578
  533. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-solar-direct-ics.xml +577 -578
  534. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-solar-fraction.xml +570 -571
  535. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-solar-indirect-flat-plate.xml +577 -578
  536. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-solar-thermosyphon-flat-plate.xml +577 -578
  537. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-coal.xml +563 -564
  538. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-elec-uef.xml +564 -0
  539. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-gas-outside.xml +563 -564
  540. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-gas-uef.xml +565 -0
  541. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-gas.xml +563 -564
  542. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-heat-pump-outside.xml +561 -562
  543. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-heat-pump-uef.xml +564 -0
  544. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-heat-pump-with-solar-fraction.xml +569 -570
  545. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-heat-pump-with-solar.xml +576 -577
  546. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-heat-pump.xml +561 -562
  547. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-oil.xml +563 -564
  548. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tank-wood.xml +563 -564
  549. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-electric-outside.xml +561 -562
  550. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-electric-uef.xml +561 -0
  551. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-electric.xml +560 -561
  552. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-gas-uef.xml +561 -0
  553. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-gas-with-solar-fraction.xml +568 -569
  554. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-gas-with-solar.xml +575 -576
  555. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-gas.xml +560 -561
  556. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-tankless-propane.xml +560 -561
  557. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-2stories-garage.xml +661 -664
  558. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-2stories.xml +575 -576
  559. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-beds-1.xml +562 -563
  560. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-beds-2.xml +562 -563
  561. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-beds-4.xml +562 -563
  562. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-beds-5.xml +562 -563
  563. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-garage.xml +636 -639
  564. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-infil-ach-house-pressure.xml +562 -563
  565. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-infil-cfm-house-pressure.xml +562 -563
  566. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-infil-cfm50.xml +562 -563
  567. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-infil-flue.xml +565 -566
  568. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-infil-natural-ach.xml +561 -562
  569. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-overhangs.xml +582 -578
  570. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-rooftypes.xml +590 -591
  571. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-skylights-shading.xml +601 -0
  572. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-skylights.xml +590 -591
  573. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-split-level.xml +517 -0
  574. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-split-surfaces.xml +2474 -2493
  575. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-split-surfaces2.xml +2475 -0
  576. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-walltypes.xml +754 -755
  577. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-windows-none.xml +504 -505
  578. data/example_files/resources/hpxml-measures/workflow/sample_files/{base-enclosure-windows-interior-shading.xml → base-enclosure-windows-shading.xml} +23 -9
  579. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-ambient.xml +498 -497
  580. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-basement-garage.xml +644 -0
  581. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-complex.xml +724 -729
  582. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-conditioned-basement-slab-insulation.xml +562 -563
  583. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-conditioned-basement-wall-interior-insulation.xml +562 -563
  584. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-multiple.xml +685 -688
  585. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-slab.xml +516 -517
  586. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-unconditioned-basement-above-grade.xml +609 -610
  587. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-unconditioned-basement-assembly-r.xml +558 -559
  588. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-unconditioned-basement-wall-insulation.xml +573 -574
  589. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-unconditioned-basement.xml +573 -574
  590. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-unvented-crawlspace.xml +573 -574
  591. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-vented-crawlspace.xml +576 -577
  592. data/example_files/resources/hpxml-measures/workflow/sample_files/base-foundation-walkout-basement.xml +627 -628
  593. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-dual-fuel-air-to-air-heat-pump-1-speed-autosize.xml → base-hvac-air-to-air-heat-pump-1-speed-cooling-only.xml} +8 -12
  594. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-air-to-air-heat-pump-1-speed-autosize-manual-s-oversize-allowances.xml → base-hvac-air-to-air-heat-pump-1-speed-heating-only.xml} +9 -9
  595. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-1-speed.xml +561 -562
  596. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-2-speed.xml +561 -562
  597. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-air-to-air-heat-pump-var-speed.xml +561 -562
  598. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-1-speed-cooling-only.xml +553 -0
  599. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-air-to-air-heat-pump-1-speed-autosize.xml → base-hvac-autosize-air-to-air-heat-pump-1-speed-heating-only.xml} +5 -6
  600. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-1-speed-manual-s-oversize-allowances.xml +561 -0
  601. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-air-to-air-heat-pump-1-speed.xml +558 -0
  602. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-air-to-air-heat-pump-2-speed-autosize-manual-s-oversize-allowances.xml → base-hvac-autosize-air-to-air-heat-pump-2-speed-manual-s-oversize-allowances.xml} +4 -5
  603. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-air-to-air-heat-pump-2-speed-autosize.xml → base-hvac-autosize-air-to-air-heat-pump-2-speed.xml} +4 -5
  604. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-air-to-air-heat-pump-var-speed-autosize-manual-s-oversize-allowances.xml → base-hvac-autosize-air-to-air-heat-pump-var-speed-manual-s-oversize-allowances.xml} +4 -5
  605. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-air-to-air-heat-pump-var-speed-autosize.xml → base-hvac-autosize-air-to-air-heat-pump-var-speed.xml} +4 -5
  606. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-boiler-elec-only-autosize.xml → base-hvac-autosize-boiler-elec-only.xml} +2 -5
  607. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-boiler-gas-central-ac-1-speed-autosize.xml → base-hvac-autosize-boiler-gas-central-ac-1-speed.xml} +4 -6
  608. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-boiler-gas-only-autosize.xml → base-hvac-autosize-boiler-gas-only.xml} +2 -5
  609. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-central-ac-only-1-speed-autosize.xml → base-hvac-autosize-central-ac-only-1-speed.xml} +547 -548
  610. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-central-ac-only-2-speed-autosize.xml → base-hvac-autosize-central-ac-only-2-speed.xml} +4 -5
  611. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-central-ac-only-var-speed-autosize.xml → base-hvac-autosize-central-ac-only-var-speed.xml} +4 -5
  612. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-central-ac-plus-air-to-air-heat-pump-heating-autosize.xml → base-hvac-autosize-central-ac-plus-air-to-air-heat-pump-heating.xml} +570 -571
  613. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-dual-fuel-air-to-air-heat-pump-1-speed.xml +559 -0
  614. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-dual-fuel-mini-split-heat-pump-ducted-autosize.xml → base-hvac-autosize-dual-fuel-mini-split-heat-pump-ducted.xml} +557 -558
  615. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-elec-resistance-only-autosize.xml → base-hvac-autosize-elec-resistance-only.xml} +2 -5
  616. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-evap-cooler-furnace-gas-autosize.xml → base-hvac-autosize-evap-cooler-furnace-gas.xml} +4 -5
  617. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-floor-furnace-propane-only-autosize.xml → base-hvac-autosize-floor-furnace-propane-only.xml} +5 -6
  618. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-furnace-elec-only-autosize.xml → base-hvac-autosize-furnace-elec-only.xml} +4 -5
  619. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-furnace-gas-central-ac-2-speed-autosize.xml → base-hvac-autosize-furnace-gas-central-ac-2-speed.xml} +4 -5
  620. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-furnace-gas-central-ac-var-speed-autosize.xml → base-hvac-autosize-furnace-gas-central-ac-var-speed.xml} +4 -5
  621. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-furnace-gas-only-autosize.xml → base-hvac-autosize-furnace-gas-only.xml} +4 -6
  622. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-furnace-gas-room-ac-autosize.xml → base-hvac-autosize-furnace-gas-room-ac.xml} +4 -5
  623. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-ground-to-air-heat-pump-cooling-only.xml +555 -0
  624. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-ground-to-air-heat-pump-heating-only.xml +560 -0
  625. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-ground-to-air-heat-pump-autosize-manual-s-oversize-allowances.xml → base-hvac-autosize-ground-to-air-heat-pump-manual-s-oversize-allowances.xml} +4 -6
  626. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-ground-to-air-heat-pump-autosize.xml → base-hvac-autosize-ground-to-air-heat-pump.xml} +4 -6
  627. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-mini-split-air-conditioner-only-ducted.xml +547 -0
  628. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-mini-split-heat-pump-ducted-cooling-only-autosize.xml → base-hvac-autosize-mini-split-heat-pump-ducted-cooling-only.xml} +551 -552
  629. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-mini-split-heat-pump-ducted-heating-only-autosize.xml → base-hvac-autosize-mini-split-heat-pump-ducted-heating-only.xml} +556 -557
  630. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-autosize-mini-split-heat-pump-ducted-manual-s-oversize-allowances.xml +560 -0
  631. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-mini-split-heat-pump-ducted-autosize.xml → base-hvac-autosize-mini-split-heat-pump-ducted.xml} +556 -557
  632. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-room-ac-only-autosize.xml → base-hvac-autosize-room-ac-only.xml} +2 -5
  633. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-stove-oil-only-autosize.xml → base-hvac-autosize-stove-oil-only.xml} +5 -6
  634. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-wall-furnace-elec-only-autosize.xml → base-hvac-autosize-wall-furnace-elec-only.xml} +5 -6
  635. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-autosize.xml → base-hvac-autosize.xml} +4 -5
  636. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-coal-only.xml +518 -521
  637. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-elec-only.xml +518 -521
  638. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-gas-central-ac-1-speed.xml +571 -573
  639. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-gas-only.xml +519 -522
  640. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-oil-only.xml +518 -521
  641. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-propane-only.xml +518 -521
  642. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-boiler-wood-only.xml +518 -521
  643. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-central-ac-only-1-speed.xml +548 -549
  644. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-central-ac-only-2-speed.xml +548 -549
  645. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-central-ac-only-var-speed.xml +548 -549
  646. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-central-ac-plus-air-to-air-heat-pump-heating.xml +575 -576
  647. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-dse.xml +532 -535
  648. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-dual-fuel-air-to-air-heat-pump-1-speed-electric.xml +562 -563
  649. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-dual-fuel-air-to-air-heat-pump-1-speed.xml +562 -563
  650. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-dual-fuel-air-to-air-heat-pump-2-speed.xml +562 -563
  651. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-dual-fuel-air-to-air-heat-pump-var-speed.xml +562 -563
  652. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-dual-fuel-mini-split-heat-pump-ducted.xml +561 -562
  653. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ducts-leakage-percent.xml +562 -563
  654. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-elec-resistance-only.xml +509 -512
  655. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-evap-cooler-furnace-gas.xml +555 -555
  656. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-evap-cooler-only-ducted.xml +536 -528
  657. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-evap-cooler-only.xml +503 -505
  658. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-fireplace-wood-only.xml +6 -7
  659. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-fixed-heater-gas-only.xml +6 -57
  660. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-floor-furnace-propane-only.xml +6 -7
  661. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-coal-only.xml +549 -0
  662. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-elec-central-ac-1-speed.xml +562 -563
  663. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-elec-only.xml +548 -549
  664. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-gas-central-ac-2-speed.xml +562 -563
  665. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-gas-central-ac-var-speed.xml +562 -563
  666. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-gas-only.xml +5 -7
  667. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-gas-room-ac.xml +560 -561
  668. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-oil-only.xml +548 -549
  669. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-propane-only.xml +548 -549
  670. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-wood-only.xml +548 -549
  671. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-furnace-x3-dse.xml +576 -579
  672. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ground-to-air-heat-pump-cooling-only.xml +557 -0
  673. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ground-to-air-heat-pump-heating-only.xml +563 -0
  674. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ground-to-air-heat-pump.xml +7 -9
  675. data/example_files/resources/hpxml-measures/workflow/sample_files/{base-hvac-flowrate.xml → base-hvac-install-quality-airflow-defect-furnace-gas-central-ac-1-speed.xml} +8 -9
  676. data/example_files/resources/hpxml-measures/workflow/sample_files/{invalid_files/heat-pump-mixed-fixed-and-autosize-capacities2.xml → base-hvac-install-quality-all-air-to-air-heat-pump-1-speed.xml} +13 -8
  677. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-all-air-to-air-heat-pump-2-speed.xml +567 -0
  678. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-all-air-to-air-heat-pump-var-speed.xml +567 -0
  679. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-all-furnace-gas-central-ac-1-speed.xml +572 -0
  680. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-all-furnace-gas-central-ac-2-speed.xml +572 -0
  681. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-all-furnace-gas-central-ac-var-speed.xml +572 -0
  682. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-all-furnace-gas-only.xml +553 -0
  683. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-all-ground-to-air-heat-pump.xml +566 -0
  684. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-mini-split-air-conditioner-only-ducted-autosize.xml → base-hvac-install-quality-all-mini-split-air-conditioner-only-ducted.xml} +10 -5
  685. data/example_files/resources/hpxml-measures/workflow/sample_files/{hvac_autosizing/base-hvac-mini-split-heat-pump-ducted-autosize-manual-s-oversize-allowances.xml → base-hvac-install-quality-all-mini-split-heat-pump-ducted.xml} +13 -8
  686. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-blower-efficiency-furnace-gas-central-ac-1-speed.xml +569 -0
  687. data/example_files/resources/hpxml-measures/workflow/sample_files/{base-misc-shelter-coefficient.xml → base-hvac-install-quality-charge-defect-furnace-gas-central-ac-1-speed.xml} +9 -10
  688. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-install-quality-none-furnace-gas-central-ac-1-speed.xml +570 -0
  689. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-air-conditioner-only-ducted.xml +547 -548
  690. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-air-conditioner-only-ductless.xml +508 -511
  691. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-heat-pump-ducted-cooling-only.xml +554 -555
  692. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-heat-pump-ducted-heating-only.xml +560 -561
  693. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-heat-pump-ducted.xml +560 -561
  694. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-mini-split-heat-pump-ductless.xml +515 -518
  695. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-multiple.xml +21 -13
  696. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-none.xml +486 -489
  697. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-portable-heater-gas-only.xml +6 -57
  698. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-programmable-thermostat-detailed.xml +567 -0
  699. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-programmable-thermostat.xml +570 -571
  700. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-room-ac-only-33percent.xml +508 -511
  701. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-room-ac-only.xml +508 -511
  702. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-setpoints.xml +562 -563
  703. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-stove-oil-only.xml +6 -7
  704. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-stove-wood-pellets-only.xml +6 -7
  705. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-undersized-allow-increased-fixed-capacities.xml +565 -566
  706. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-undersized.xml +562 -563
  707. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-wall-furnace-elec-only.xml +6 -7
  708. data/example_files/resources/hpxml-measures/workflow/sample_files/base-lighting-ceiling-fans.xml +573 -574
  709. data/example_files/resources/hpxml-measures/workflow/sample_files/base-lighting-detailed.xml +585 -586
  710. data/example_files/resources/hpxml-measures/workflow/sample_files/base-lighting-none.xml +488 -489
  711. data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-AMY-2012.xml +562 -563
  712. data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-baltimore-md.xml +573 -563
  713. data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-dallas-tx.xml +516 -517
  714. data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-duluth-mn.xml +573 -563
  715. data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-helena-mt.xml +563 -0
  716. data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-honolulu-hi.xml +517 -0
  717. data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-miami-fl.xml +516 -517
  718. data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-phoenix-az.xml +517 -0
  719. data/example_files/resources/hpxml-measures/workflow/sample_files/base-location-portland-or.xml +577 -0
  720. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-balanced.xml +574 -575
  721. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-bath-kitchen-fans.xml +590 -591
  722. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-cfis-dse.xml +545 -548
  723. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-cfis-evap-cooler-only-ducted.xml +549 -541
  724. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-cfis.xml +575 -576
  725. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-erv-atre-asre.xml +576 -577
  726. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-erv.xml +576 -577
  727. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-exhaust-rated-flow-rate.xml +574 -575
  728. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-exhaust.xml +574 -575
  729. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-hrv-asre.xml +575 -576
  730. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-hrv.xml +575 -576
  731. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-multiple.xml +796 -795
  732. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-supply.xml +574 -575
  733. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-whole-house-fan.xml +572 -573
  734. data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-defaults.xml +478 -495
  735. data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-generators.xml +579 -0
  736. data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-loads-large-uncommon.xml +758 -833
  737. data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-loads-large-uncommon2.xml +749 -820
  738. data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-loads-none.xml +550 -559
  739. data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-neighbor-shading.xml +575 -576
  740. data/example_files/resources/hpxml-measures/workflow/sample_files/{invalid_files/invalid-calendar-year.xml → base-misc-shielding-of-home.xml} +7 -8
  741. data/example_files/resources/hpxml-measures/workflow/sample_files/base-misc-usage-multiplier.xml +728 -725
  742. data/example_files/resources/hpxml-measures/workflow/sample_files/base-multiple-buildings.xml +1657 -0
  743. data/example_files/resources/hpxml-measures/workflow/sample_files/base-pv.xml +6 -7
  744. data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-stochastic-vacant.xml +564 -0
  745. data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-stochastic.xml +6 -7
  746. data/example_files/resources/hpxml-measures/workflow/sample_files/base-schedules-user-specified.xml +6 -7
  747. data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-calendar-year-custom.xml +563 -564
  748. data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-daylight-saving-custom.xml +569 -570
  749. data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-daylight-saving-disabled.xml +565 -566
  750. data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-runperiod-1-month.xml +566 -567
  751. data/example_files/resources/hpxml-measures/workflow/sample_files/base-simcontrol-timestep-10-mins.xml +562 -563
  752. data/example_files/resources/hpxml-measures/workflow/sample_files/base.xml +562 -563
  753. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/boiler-invalid-afue.xml +519 -0
  754. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/cfis-with-hydronic-distribution.xml +532 -535
  755. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/clothes-dryer-location.xml +562 -563
  756. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/clothes-washer-location.xml +562 -563
  757. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/cooking-range-location.xml +562 -563
  758. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/dehumidifier-fraction-served.xml +535 -0
  759. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/dehumidifier-setpoints.xml +535 -0
  760. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/dhw-frac-load-served.xml +575 -578
  761. data/example_files/resources/hpxml-measures/workflow/sample_files/{base-dhw-uef.xml → invalid_files/dhw-invalid-ef-tank.xml} +7 -8
  762. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/dhw-invalid-uef-tank-heat-pump.xml +564 -0
  763. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/dishwasher-location.xml +562 -563
  764. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/duct-leakage-cfm25.xml +563 -0
  765. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/duct-leakage-percent.xml +563 -0
  766. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/duct-location-unconditioned-space.xml +562 -563
  767. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/duct-location.xml +562 -563
  768. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/duplicate-id.xml +562 -563
  769. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/enclosure-attic-missing-roof.xml +546 -547
  770. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/enclosure-basement-missing-exterior-foundation-wall.xml +543 -544
  771. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/enclosure-basement-missing-slab.xml +546 -545
  772. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/enclosure-floor-area-exceeds-cfa.xml +563 -0
  773. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/enclosure-floor-area-exceeds-cfa2.xml +448 -0
  774. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/enclosure-garage-missing-exterior-wall.xml +613 -616
  775. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/enclosure-garage-missing-roof-ceiling.xml +626 -629
  776. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/enclosure-garage-missing-slab.xml +610 -611
  777. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/enclosure-living-missing-ceiling-roof.xml +550 -551
  778. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/enclosure-living-missing-exterior-wall.xml +472 -473
  779. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/enclosure-living-missing-floor-slab.xml +488 -534
  780. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/frac-sensible-fuel-load.xml +760 -0
  781. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/frac-sensible-plug-load.xml +759 -0
  782. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/frac-total-fuel-load.xml +761 -0
  783. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/frac-total-plug-load.xml +759 -0
  784. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/furnace-invalid-afue.xml +563 -0
  785. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/generator-number-of-bedrooms-served.xml +460 -0
  786. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/generator-output-greater-than-consumption.xml +579 -0
  787. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/heat-pump-mixed-fixed-and-autosize-capacities.xml +559 -560
  788. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/hvac-distribution-multiple-attached-cooling.xml +21 -13
  789. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/hvac-distribution-multiple-attached-heating.xml +21 -13
  790. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/hvac-distribution-return-duct-leakage-missing.xml +528 -534
  791. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/hvac-dse-multiple-attached-cooling.xml +546 -549
  792. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/hvac-dse-multiple-attached-heating.xml +546 -549
  793. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/hvac-frac-load-served.xml +21 -13
  794. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/hvac-inconsistent-fan-powers.xml +569 -0
  795. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/hvac-invalid-distribution-system-type.xml +570 -571
  796. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/hvac-shared-negative-seer-eq.xml +407 -0
  797. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-assembly-effective-rvalue.xml +563 -0
  798. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-datatype-boolean.xml +563 -0
  799. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-datatype-float.xml +563 -0
  800. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-datatype-integer.xml +563 -0
  801. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-daylight-saving.xml +569 -567
  802. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-distribution-cfa-served.xml +562 -563
  803. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-epw-filepath.xml +562 -563
  804. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-facility-type-equipment.xml +466 -0
  805. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-facility-type-surfaces.xml +644 -0
  806. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/{appliances-location-unconditioned-space.xml → invalid-foundation-wall-properties.xml} +39 -29
  807. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-id.xml +591 -0
  808. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-id2.xml +591 -0
  809. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-infiltration-volume.xml +563 -0
  810. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-input-parameters.xml +565 -0
  811. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-neighbor-shading-azimuth.xml +575 -576
  812. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-number-of-bedrooms-served.xml +465 -0
  813. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/{slab-zero-exposed-perimeter.xml → invalid-number-of-conditioned-floors.xml} +7 -8
  814. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-number-of-units-served.xml +451 -0
  815. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-relatedhvac-desuperheater.xml +550 -551
  816. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-relatedhvac-dhw-indirect.xml +517 -520
  817. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-runperiod.xml +564 -565
  818. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-schema-version.xml +563 -0
  819. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-shared-vent-in-unit-flowrate.xml +473 -0
  820. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-timestep.xml +562 -563
  821. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-window-height.xml +582 -578
  822. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/lighting-fractions.xml +562 -563
  823. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/missing-duct-location.xml +21 -13
  824. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/missing-elements.xml +560 -561
  825. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/multifamily-reference-appliance.xml +562 -563
  826. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/multifamily-reference-duct.xml +562 -563
  827. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/multifamily-reference-surface.xml +575 -566
  828. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/multifamily-reference-water-heater.xml +562 -563
  829. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/multiple-buildings-without-building-id.xml +1657 -0
  830. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/multiple-buildings-wrong-building-id.xml +1657 -0
  831. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/multiple-shared-cooling-systems.xml +432 -0
  832. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/multiple-shared-heating-systems.xml +434 -0
  833. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/net-area-negative-roof.xml +590 -591
  834. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/net-area-negative-wall.xml +562 -563
  835. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/num-bedrooms-exceeds-limit.xml +563 -0
  836. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/orphaned-hvac-distribution.xml +546 -547
  837. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/refrigerator-location.xml +562 -563
  838. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/refrigerators-multiple-primary.xml +568 -569
  839. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/refrigerators-no-primary.xml +568 -569
  840. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/repeated-relatedhvac-desuperheater.xml +563 -564
  841. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/repeated-relatedhvac-dhw-indirect.xml +526 -529
  842. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/solar-fraction-one.xml +571 -0
  843. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/solar-thermal-system-with-combi-tankless.xml +531 -534
  844. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/solar-thermal-system-with-desuperheater.xml +565 -566
  845. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/solar-thermal-system-with-dhw-indirect.xml +531 -534
  846. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/unattached-cfis.xml +575 -576
  847. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/unattached-door.xml +562 -563
  848. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/unattached-hvac-distribution.xml +562 -563
  849. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/unattached-shared-clothes-washer-water-heater.xml +465 -827
  850. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/unattached-shared-dishwasher-water-heater.xml +465 -827
  851. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/unattached-skylight.xml +590 -591
  852. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/unattached-solar-thermal-system.xml +577 -578
  853. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/unattached-window.xml +562 -563
  854. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/water-heater-location-other.xml +562 -563
  855. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/water-heater-location.xml +562 -563
  856. data/example_files/resources/hpxml-measures/workflow/template.osw +5 -1
  857. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L100AC.xml +6 -17
  858. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L100AL.xml +6 -17
  859. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L110AC.xml +6 -17
  860. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L110AL.xml +6 -17
  861. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L120AC.xml +6 -17
  862. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L120AL.xml +6 -17
  863. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L130AC.xml +6 -17
  864. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L130AL.xml +6 -17
  865. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L140AC.xml +6 -17
  866. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L140AL.xml +6 -17
  867. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L150AC.xml +6 -17
  868. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L150AL.xml +6 -17
  869. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L155AC.xml +6 -17
  870. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L155AL.xml +6 -17
  871. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L160AC.xml +6 -17
  872. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L160AL.xml +6 -17
  873. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L170AC.xml +6 -17
  874. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L170AL.xml +6 -17
  875. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L200AC.xml +6 -17
  876. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L200AL.xml +6 -17
  877. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L202AC.xml +6 -17
  878. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L202AL.xml +6 -17
  879. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L302XC.xml +6 -19
  880. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L304XC.xml +6 -19
  881. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L322XC.xml +6 -19
  882. data/example_files/resources/hpxml-measures/workflow/tests/ASHRAE_Standard_140/L324XC.xml +6 -19
  883. data/example_files/resources/hpxml-measures/workflow/tests/base_results/results.csv +294 -0
  884. data/example_files/resources/hpxml-measures/workflow/tests/base_results/results_ashrae_140.csv +27 -0
  885. data/example_files/resources/hpxml-measures/workflow/tests/base_results/results_hvac_sizing.csv +294 -0
  886. data/example_files/resources/hpxml-measures/workflow/tests/compare.rb +130 -0
  887. data/example_files/resources/hpxml-measures/workflow/tests/hpxml_translator_test.rb +522 -527
  888. data/example_files/{measures/BuildResidentialModel/resources → resources}/measure-info.json +0 -0
  889. data/example_files/{measures/BuildResidentialModel/resources → resources}/meta_measure.rb +53 -44
  890. data/example_files/validation_schema.yaml +149 -0
  891. data/example_files/visualization/input_visualization_feature.html +213 -56
  892. data/example_files/visualization/input_visualization_scenario.html +92 -30
  893. data/lib/uo_cli.rb +406 -128
  894. data/lib/uo_cli/version.rb +17 -7
  895. data/requirements.txt +2 -0
  896. data/scripts/setup-env-gitbash.sh +5 -5
  897. data/scripts/setup-env-unix.sh +4 -4
  898. data/scripts/setup-env.bat +14 -11
  899. data/scripts/setup-env.ps1 +13 -10
  900. data/uo_cli.gemspec +10 -8
  901. metadata +390 -130
  902. data/developer_nrel_key.rb +0 -31
  903. data/example_files/measures/ResidentialGeometryCreateMultifamily/measure.rb +0 -1005
  904. data/example_files/measures/ResidentialGeometryCreateMultifamily/measure.xml +0 -326
  905. data/example_files/measures/ResidentialGeometryCreateMultifamily/tests/create_residential_multifamily_geometry_test.rb +0 -477
  906. data/example_files/measures/ResidentialGeometryCreateSingleFamilyAttached/measure.rb +0 -1039
  907. data/example_files/measures/ResidentialGeometryCreateSingleFamilyAttached/measure.xml +0 -393
  908. data/example_files/measures/ResidentialGeometryCreateSingleFamilyAttached/tests/create_residential_single_family_attached_geometry_test.rb +0 -456
  909. data/example_files/measures/ResidentialGeometryCreateSingleFamilyDetached/measure.rb +0 -979
  910. data/example_files/measures/ResidentialGeometryCreateSingleFamilyDetached/measure.xml +0 -388
  911. data/example_files/measures/ResidentialGeometryCreateSingleFamilyDetached/tests/create_residential_single_family_detached_geometry_test.rb +0 -704
  912. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/resources/location.rb +0 -24
  913. data/example_files/resources/hpxml-measures/BuildResidentialHPXML/resources/schedules_config.yml +0 -61
  914. data/example_files/resources/hpxml-measures/docs/source/hpxml_to_openstudio.rst +0 -1386
  915. data/example_files/resources/hpxml-measures/docs/source/simulation_output_report.rst +0 -252
  916. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-shared-laundry-room.xml +0 -828
  917. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-shared-water-heater-recirc.xml +0 -820
  918. data/example_files/resources/hpxml-measures/workflow/sample_files/base-dhw-shared-water-heater.xml +0 -813
  919. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-attached-multifamily.xml +0 -810
  920. data/example_files/resources/hpxml-measures/workflow/sample_files/base-enclosure-common-surfaces.xml +0 -928
  921. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-ideal-air.xml +0 -501
  922. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-multiple2.xml +0 -838
  923. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-boiler-chiller-baseboard.xml +0 -777
  924. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-boiler-chiller-fan-coil-ducted.xml +0 -808
  925. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-boiler-chiller-fan-coil.xml +0 -780
  926. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-boiler-chiller-water-loop-heat-pump.xml +0 -820
  927. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-boiler-cooling-tower-water-loop-heat-pump.xml +0 -815
  928. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-boiler-only-baseboard.xml +0 -760
  929. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-boiler-only-fan-coil-ducted.xml +0 -790
  930. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-boiler-only-fan-coil-eae.xml +0 -759
  931. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-boiler-only-fan-coil.xml +0 -762
  932. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-boiler-only-water-loop-heat-pump.xml +0 -796
  933. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-chiller-only-baseboard.xml +0 -759
  934. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-chiller-only-fan-coil-ducted.xml +0 -789
  935. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-chiller-only-fan-coil.xml +0 -761
  936. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-chiller-only-water-loop-heat-pump.xml +0 -796
  937. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-cooling-tower-only-water-loop-heat-pump.xml +0 -791
  938. data/example_files/resources/hpxml-measures/workflow/sample_files/base-hvac-shared-ground-loop-ground-to-air-heat-pump.xml +0 -814
  939. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-shared-preconditioning.xml +0 -851
  940. data/example_files/resources/hpxml-measures/workflow/sample_files/base-mechvent-shared.xml +0 -835
  941. data/example_files/resources/hpxml-measures/workflow/sample_files/base-pv-shared.xml +0 -827
  942. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/coal-for-non-boiler-heating.xml +0 -514
  943. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-facility-type.xml +0 -828
  944. data/example_files/resources/hpxml-measures/workflow/sample_files/invalid_files/invalid-window-interior-shading.xml +0 -564
@@ -15,6 +15,13 @@ class HVAC
15
15
  obj_name = Constants.ObjectNameCentralAirConditionerAndFurnace
16
16
  end
17
17
 
18
+ if not heating_system.nil?
19
+ htg_ap = heating_system.additional_properties
20
+ end
21
+ if not cooling_system.nil?
22
+ clg_ap = cooling_system.additional_properties
23
+ end
24
+
18
25
  if not heating_system.nil?
19
26
  sequential_heat_load_frac = calc_sequential_load_fraction(heating_system.fraction_heat_load_served, remaining_heat_load_frac)
20
27
  else
@@ -26,84 +33,14 @@ class HVAC
26
33
  sequential_cool_load_frac = 0.0
27
34
  end
28
35
 
36
+ # Cooling Coil
29
37
  if not cooling_system.nil?
30
- if cooling_system.compressor_type == HPXML::HVACCompressorTypeSingleStage
31
- num_speeds = 1
32
- elsif cooling_system.compressor_type == HPXML::HVACCompressorTypeTwoStage
33
- num_speeds = 2
34
- elsif cooling_system.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
35
- num_speeds = 4
36
- end
37
- fan_power_rated = get_fan_power_rated(cooling_system.cooling_efficiency_seer)
38
- crankcase_kw, crankcase_temp = get_crankcase_assumptions(cooling_system.fraction_cool_load_served)
39
-
40
- # Cooling Coil
41
-
42
- cool_c_d = get_cool_c_d(num_speeds, cooling_system.cooling_efficiency_seer)
43
- cool_cfm = cooling_system.cooling_cfm
44
- if num_speeds == 1
45
- cool_rated_airflow_rate = 386.1 # cfm/ton
46
- cool_capacity_ratios = [1.0]
47
- cool_fan_speed_ratios = [1.0]
48
- cool_shrs = [cooling_system.cooling_shr]
49
- cool_cap_ft_spec = [[3.670270705, -0.098652414, 0.000955906, 0.006552414, -0.0000156, -0.000131877]]
50
- cool_eir_ft_spec = [[-3.302695861, 0.137871531, -0.001056996, -0.012573945, 0.000214638, -0.000145054]]
51
- cool_cap_fflow_spec = [[0.718605468, 0.410099989, -0.128705457]]
52
- cool_eir_fflow_spec = [[1.32299905, -0.477711207, 0.154712157]]
53
- cool_eers = [calc_eer_cooling_1speed(cooling_system.cooling_efficiency_seer, fan_power_rated, cool_eir_ft_spec)]
54
- elsif num_speeds == 2
55
- cool_rated_airflow_rate = 355.2 # cfm/ton
56
- cool_capacity_ratios = [0.72, 1.0]
57
- cool_fan_speed_ratios = [0.86, 1.0]
58
- cool_shrs = [cooling_system.cooling_shr - 0.02, cooling_system.cooling_shr] # TODO: is the following assumption correct (revisit Dylan's data?)? OR should value from HPXML be used for both stages
59
- cool_cap_ft_spec = [[3.940185508, -0.104723455, 0.001019298, 0.006471171, -0.00000953, -0.000161658],
60
- [3.109456535, -0.085520461, 0.000863238, 0.00863049, -0.0000210, -0.000140186]]
61
- cool_eir_ft_spec = [[-3.877526888, 0.164566276, -0.001272755, -0.019956043, 0.000256512, -0.000133539],
62
- [-1.990708931, 0.093969249, -0.00073335, -0.009062553, 0.000165099, -0.0000997]]
63
- cool_cap_fflow_spec = [[0.65673024, 0.516470835, -0.172887149],
64
- [0.690334551, 0.464383753, -0.154507638]]
65
- cool_eir_fflow_spec = [[1.562945114, -0.791859997, 0.230030877],
66
- [1.31565404, -0.482467162, 0.166239001]]
67
- cool_eers = calc_eers_cooling_2speed(runner, cooling_system.cooling_efficiency_seer, cool_c_d, cool_capacity_ratios, cool_fan_speed_ratios, fan_power_rated, cool_eir_ft_spec, cool_cap_ft_spec)
68
- elsif num_speeds == 4
69
- cool_rated_airflow_rate = 411.0 # cfm/ton
70
- cool_capacity_ratios = [0.36, 0.51, 0.67, 1.0]
71
- cool_fan_speed_ratios = [0.42, 0.54, 0.68, 1.0]
72
- cool_shrs = [1.115, 1.026, 1.013, 1.0].map { |mult| cooling_system.cooling_shr * mult }
73
- # The following coefficients were generated using NREL experimental performance mapping for the Carrier unit
74
- cool_cap_coeff_perf_map = [[1.6516044444444447, 0.0698916049382716, -0.0005546296296296296, -0.08870160493827162, 0.0004135802469135802, 0.00029077160493827157],
75
- [-6.84948049382716, 0.26946, -0.0019413580246913577, -0.03281469135802469, 0.00015694444444444442, 3.32716049382716e-05],
76
- [-4.53543086419753, 0.15358543209876546, -0.0009345679012345678, 0.002666913580246914, -7.993827160493826e-06, -0.00011617283950617283],
77
- [-3.500948395061729, 0.11738987654320988, -0.0006580246913580248, 0.007003148148148148, -2.8518518518518517e-05, -0.0001284259259259259],
78
- [1.8769221728395058, -0.04768641975308643, 0.0006885802469135801, 0.006643395061728395, 1.4209876543209876e-05, -0.00024043209876543206]]
79
- cool_cap_ft_spec = cool_cap_coeff_perf_map.select { |i| [0, 1, 2, 4].include? cool_cap_coeff_perf_map.index(i) }
80
- cool_cap_ft_spec_3 = cool_cap_coeff_perf_map.select { |i| [0, 1, 4].include? cool_cap_coeff_perf_map.index(i) }
81
- cool_eir_coeff_perf_map = [[2.896298765432099, -0.12487654320987657, 0.0012148148148148148, 0.04492037037037037, 8.734567901234567e-05, -0.0006348765432098764],
82
- [6.428076543209876, -0.20913209876543212, 0.0018521604938271604, 0.024392592592592594, 0.00019691358024691356, -0.0006012345679012346],
83
- [5.136356049382716, -0.1591530864197531, 0.0014151234567901232, 0.018665555555555557, 0.00020398148148148147, -0.0005407407407407407],
84
- [1.3823471604938273, -0.02875123456790123, 0.00038302469135802463, 0.006344814814814816, 0.00024836419753086417, -0.00047469135802469134],
85
- [-1.0411735802469133, 0.055261604938271605, -0.0004404320987654321, 0.0002154938271604939, 0.00017484567901234564, -0.0002017901234567901]]
86
- cool_eir_ft_spec = cool_eir_coeff_perf_map.select { |i| [0, 1, 2, 4].include? cool_eir_coeff_perf_map.index(i) }
87
- cool_eir_ft_spec_3 = cool_eir_coeff_perf_map.select { |i| [0, 1, 4].include? cool_eir_coeff_perf_map.index(i) }
88
- cool_cap_fflow_spec = [[1, 0, 0]] * 4
89
- cool_eir_fflow_spec = [[1, 0, 0]] * 4
90
- cap_ratio_seer_3 = cool_capacity_ratios.select { |i| [0, 1, 3].include? cool_capacity_ratios.index(i) }
91
- fan_speed_seer_3 = cool_fan_speed_ratios.select { |i| [0, 1, 3].include? cool_fan_speed_ratios.index(i) }
92
- cool_eers = calc_eers_cooling_4speed(runner, cooling_system.cooling_efficiency_seer, cool_c_d, cap_ratio_seer_3, fan_speed_seer_3, fan_power_rated, cool_eir_ft_spec_3, cool_cap_ft_spec_3)
93
- end
94
- cool_cfms_ton_rated = calc_cfms_ton_rated(cool_rated_airflow_rate, cool_fan_speed_ratios, cool_capacity_ratios)
95
- cool_shrs_rated_gross = calc_shrs_rated_gross(num_speeds, cool_shrs, fan_power_rated, cool_cfms_ton_rated)
96
- cool_eirs = calc_cool_eirs(num_speeds, cool_eers, fan_power_rated)
97
- cool_closs_fplr_spec = [calc_plr_coefficients(cool_c_d)] * num_speeds
98
- clg_coil = create_dx_cooling_coil(model, obj_name, (0...num_speeds).to_a, cool_eirs, cool_cap_ft_spec, cool_eir_ft_spec, cool_closs_fplr_spec, cool_cap_fflow_spec, cool_eir_fflow_spec, cool_shrs_rated_gross, cooling_system.cooling_capacity, crankcase_kw, crankcase_temp, fan_power_rated)
38
+ clg_coil = create_dx_cooling_coil(model, obj_name, cooling_system)
99
39
  hvac_map[cooling_system.id] << clg_coil
100
40
  end
101
41
 
42
+ # Heating Coil
102
43
  if not heating_system.nil?
103
- heat_cfm = heating_system.heating_cfm
104
-
105
- # Heating Coil
106
-
107
44
  if heating_system.heating_system_fuel == HPXML::FuelTypeElectricity
108
45
  htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model)
109
46
  htg_coil.setEfficiency(heating_system.heating_efficiency_afue)
@@ -112,23 +49,39 @@ class HVAC
112
49
  htg_coil.setGasBurnerEfficiency(heating_system.heating_efficiency_afue)
113
50
  htg_coil.setParasiticElectricLoad(0)
114
51
  htg_coil.setParasiticGasLoad(0)
115
- htg_coil.setFuelType(EPlus.input_fuel_map(heating_system.heating_system_fuel))
52
+ htg_coil.setFuelType(EPlus.fuel_type(heating_system.heating_system_fuel))
116
53
  end
54
+ htg_coil.setNominalCapacity(UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W'))
117
55
  htg_coil.setName(obj_name + ' htg coil')
118
- if not heating_system.heating_capacity.nil?
119
- htg_coil.setNominalCapacity(UnitConversions.convert([heating_system.heating_capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
120
- end
121
56
  hvac_map[heating_system.id] << htg_coil
122
57
  end
123
58
 
124
59
  # Fan
60
+ if (not cooling_system.nil?) && (not heating_system.nil?) && (cooling_system.fan_watts_per_cfm.to_f != heating_system.fan_watts_per_cfm.to_f)
61
+ fail "Fan powers for heating system '#{heating_system.id}' and cooling system '#{cooling_system.id}' are attached to a single distribution system and therefore must be the same."
62
+ end
125
63
 
64
+ if (not cooling_system.nil?) && (not cooling_system.fan_watts_per_cfm.nil?)
65
+ fan_watts_per_cfm = cooling_system.fan_watts_per_cfm
66
+ else
67
+ fan_watts_per_cfm = heating_system.fan_watts_per_cfm
68
+ end
126
69
  if not cooling_system.nil?
127
- fan_power_installed = get_fan_power_installed(cooling_system.cooling_efficiency_seer)
70
+ num_speeds = clg_ap.num_speeds
128
71
  else
129
- fan_power_installed = 0.5 # W/cfm; For fuel furnaces, will be overridden by EAE later
72
+ num_speeds = 1
73
+ end
74
+ if not heating_system.nil?
75
+ htg_cfm = heating_system.heating_airflow_cfm
76
+ end
77
+ if not cooling_system.nil?
78
+ clg_cfm = cooling_system.cooling_airflow_cfm
79
+ end
80
+ fan_cfm = [htg_cfm.to_f, clg_cfm.to_f].max
81
+ if not cooling_system.nil?
82
+ fan_cfm *= clg_ap.cool_fan_speed_ratios.max
130
83
  end
131
- fan = create_supply_fan(model, obj_name, num_speeds, fan_power_installed)
84
+ fan = create_supply_fan(model, obj_name, num_speeds, fan_watts_per_cfm, fan_cfm)
132
85
  if not cooling_system.nil?
133
86
  hvac_map[cooling_system.id] += disaggregate_fan_or_pump(model, fan, nil, clg_coil, nil)
134
87
  end
@@ -137,8 +90,7 @@ class HVAC
137
90
  end
138
91
 
139
92
  # Unitary System
140
-
141
- air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, nil, clg_cfm: cool_cfm, htg_cfm: heat_cfm)
93
+ air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, nil, htg_cfm, clg_cfm)
142
94
  if not cooling_system.nil?
143
95
  hvac_map[cooling_system.id] << air_loop_unitary
144
96
  end
@@ -146,20 +98,19 @@ class HVAC
146
98
  hvac_map[heating_system.id] << air_loop_unitary
147
99
  end
148
100
 
101
+ # Unitary System Performance
149
102
  if (not cooling_system.nil?) && (num_speeds > 1)
150
- # Unitary System Performance
151
103
  perf = OpenStudio::Model::UnitarySystemPerformanceMultispeed.new(model)
152
104
  perf.setSingleModeOperation(false)
153
105
  for speed in 1..num_speeds
154
- f = OpenStudio::Model::SupplyAirflowRatioField.fromCoolingRatio(cool_fan_speed_ratios[speed - 1])
106
+ f = OpenStudio::Model::SupplyAirflowRatioField.fromCoolingRatio(clg_ap.cool_fan_speed_ratios[speed - 1])
155
107
  perf.addSupplyAirflowRatioField(f)
156
108
  end
157
109
  air_loop_unitary.setDesignSpecificationMultispeedObject(perf)
158
110
  end
159
111
 
160
112
  # Air Loop
161
-
162
- air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_frac, sequential_cool_load_frac)
113
+ air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_frac, sequential_cool_load_frac, fan_cfm)
163
114
  if not cooling_system.nil?
164
115
  hvac_map[cooling_system.id] << air_loop
165
116
  end
@@ -167,17 +118,8 @@ class HVAC
167
118
  hvac_map[heating_system.id] << air_loop
168
119
  end
169
120
 
170
- # Store info for HVAC Sizing measure
171
- if not cooling_system.nil?
172
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACCapacityRatioCooling, cool_capacity_ratios.join(','))
173
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACRatedCFMperTonCooling, cool_cfms_ton_rated.join(','))
174
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACFracCoolLoadServed, cooling_system.fraction_cool_load_served)
175
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACCoolType, Constants.ObjectNameCentralAirConditioner)
176
- end
177
- if not heating_system.nil?
178
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACFracHeatLoadServed, heating_system.fraction_heat_load_served)
179
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACHeatType, Constants.ObjectNameFurnace)
180
- end
121
+ # HVAC Installation Quality
122
+ apply_installation_quality(model, heating_system, cooling_system, air_loop_unitary, htg_coil, clg_coil, control_zone)
181
123
  end
182
124
 
183
125
  def self.apply_room_air_conditioner(model, runner, cooling_system,
@@ -187,73 +129,57 @@ class HVAC
187
129
  hvac_map[cooling_system.id] = []
188
130
  obj_name = Constants.ObjectNameRoomAirConditioner
189
131
  sequential_cool_load_frac = calc_sequential_load_fraction(cooling_system.fraction_cool_load_served, remaining_cool_load_frac)
190
- airflow_rate = 350.0 # cfm/ton; assumed
132
+
133
+ clg_ap = cooling_system.additional_properties
191
134
 
192
135
  # Performance curves
193
- # From Frigidaire 10.7 eer unit in Winkler et. al. Lab Testing of Window ACs (2013)
194
-
195
- cool_cap_ft_spec = [0.43945980246913574, -0.0008922469135802481, 0.00013984567901234569, 0.0038489259259259253, -5.6327160493827156e-05, 2.041358024691358e-05]
196
- cool_cap_ft_spec_si = convert_curve_biquadratic(cool_cap_ft_spec)
197
- cool_eir_ft_spec = [6.310506172839506, -0.17705185185185185, 0.0014645061728395061, 0.012571604938271608, 0.0001493827160493827, -0.00040308641975308644]
198
- cool_eir_ft_spec_si = convert_curve_biquadratic(cool_eir_ft_spec)
199
- cool_cap_fflow_spec = [0.887, 0.1128, 0]
200
- cool_eir_fflow_spec = [1.763, -0.6081, 0]
201
- cool_plf_fplr = [0.78, 0.22, 0]
202
- cfms_ton_rated = [312] # cfm/ton, medium speed
203
-
204
- roomac_cap_ft_curve = create_curve_biquadratic(model, cool_cap_ft_spec_si, 'RoomAC-Cap-fT', 0, 100, 0, 100)
205
- roomac_cap_fff_curve = create_curve_quadratic(model, cool_cap_fflow_spec, 'RoomAC-Cap-fFF', 0, 2, 0, 2)
206
- roomac_eir_ft_curve = create_curve_biquadratic(model, cool_eir_ft_spec_si, 'RoomAC-eir-fT', 0, 100, 0, 100)
207
- roomcac_eir_fff_curve = create_curve_quadratic(model, cool_eir_fflow_spec, 'RoomAC-eir-fFF', 0, 2, 0, 2)
208
- roomac_plf_fplr_curve = create_curve_quadratic(model, cool_plf_fplr, 'RoomAC-PLF-fPLR', 0, 1, 0, 1)
136
+ cool_cap_ft_spec_si = convert_curve_biquadratic(clg_ap.cool_cap_ft_spec[0])
137
+ cool_eir_ft_spec_si = convert_curve_biquadratic(clg_ap.cool_eir_ft_spec[0])
209
138
 
210
- # Cooling Coil
139
+ roomac_cap_ft_curve = create_curve_biquadratic(model, cool_cap_ft_spec_si, 'Cool-CAP-fT', 0, 100, 0, 100)
140
+ roomac_cap_fff_curve = create_curve_quadratic(model, clg_ap.cool_cap_fflow_spec[0], 'Cool-CAP-fFF', 0, 2, 0, 2)
141
+ roomac_eir_ft_curve = create_curve_biquadratic(model, cool_eir_ft_spec_si, 'Cool-EIR-fT', 0, 100, 0, 100)
142
+ roomcac_eir_fff_curve = create_curve_quadratic(model, clg_ap.cool_eir_fflow_spec[0], 'Cool-EIR-fFF', 0, 2, 0, 2)
143
+ roomac_plf_fplr_curve = create_curve_quadratic(model, clg_ap.cool_plf_fplr_spec[0], 'Cool-PLF-fPLR', 0, 1, 0, 1)
211
144
 
145
+ # Cooling Coil
212
146
  clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model, model.alwaysOnDiscreteSchedule, roomac_cap_ft_curve, roomac_cap_fff_curve, roomac_eir_ft_curve, roomcac_eir_fff_curve, roomac_plf_fplr_curve)
213
147
  clg_coil.setName(obj_name + ' clg coil')
214
- if not cooling_system.cooling_capacity.nil?
215
- clg_coil.setRatedTotalCoolingCapacity(UnitConversions.convert([cooling_system.cooling_capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
216
- end
217
148
  clg_coil.setRatedSensibleHeatRatio(cooling_system.cooling_shr)
218
149
  clg_coil.setRatedCOP(UnitConversions.convert(cooling_system.cooling_efficiency_eer, 'Btu/hr', 'W'))
219
150
  clg_coil.setRatedEvaporatorFanPowerPerVolumeFlowRate(773.3)
220
151
  clg_coil.setEvaporativeCondenserEffectiveness(0.9)
221
152
  clg_coil.setMaximumOutdoorDryBulbTemperatureForCrankcaseHeaterOperation(10)
222
153
  clg_coil.setBasinHeaterSetpointTemperature(2)
154
+ clg_coil.setRatedTotalCoolingCapacity(UnitConversions.convert(cooling_system.cooling_capacity, 'Btu/hr', 'W'))
155
+ clg_coil.setRatedAirFlowRate(calc_rated_airflow(cooling_system.cooling_capacity, clg_ap.cool_rated_cfm_per_ton[0], 1.0))
223
156
  hvac_map[cooling_system.id] << clg_coil
224
157
 
225
158
  # Fan
226
-
227
- fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
228
- fan.setName(obj_name + ' supply fan')
229
- fan.setEndUseSubcategory('supply fan')
230
- fan.setFanEfficiency(1)
231
- fan.setPressureRise(0)
232
- fan.setMotorEfficiency(1)
233
- fan.setMotorInAirstreamFraction(0)
159
+ clg_cfm = cooling_system.cooling_airflow_cfm
160
+ fan = create_supply_fan(model, obj_name, 1, 0.0, clg_cfm) # Fan power included in EER (net COP) above
234
161
  hvac_map[cooling_system.id] += disaggregate_fan_or_pump(model, fan, nil, clg_coil, nil)
235
162
 
236
163
  # Heating Coil (none)
237
-
238
164
  htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, model.alwaysOffDiscreteSchedule())
165
+ htg_coil.setNominalCapacity(0.0)
239
166
  htg_coil.setName(obj_name + ' htg coil')
240
167
 
241
168
  # PTAC
242
-
243
169
  ptac = OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner.new(model, model.alwaysOnDiscreteSchedule, fan, htg_coil, clg_coil)
244
170
  ptac.setName(obj_name)
245
171
  ptac.setSupplyAirFanOperatingModeSchedule(model.alwaysOffDiscreteSchedule)
172
+ ptac.setSupplyAirFlowRateDuringCoolingOperation(UnitConversions.convert(clg_cfm, 'cfm', 'm^3/s'))
173
+ ptac.setSupplyAirFlowRateDuringHeatingOperation(0.00001)
174
+ ptac.setSupplyAirFlowRateWhenNoCoolingorHeatingisNeeded(0.0)
175
+ ptac.setOutdoorAirFlowRateDuringCoolingOperation(0.0)
176
+ ptac.setOutdoorAirFlowRateDuringHeatingOperation(0.0)
177
+ ptac.setOutdoorAirFlowRateWhenNoCoolingorHeatingisNeeded(0.0)
246
178
  ptac.addToThermalZone(control_zone)
247
179
  hvac_map[cooling_system.id] << ptac
248
180
 
249
181
  control_zone.setSequentialCoolingFractionSchedule(ptac, get_sequential_load_schedule(model, sequential_cool_load_frac))
250
182
  control_zone.setSequentialHeatingFractionSchedule(ptac, get_sequential_load_schedule(model, 0))
251
-
252
- # Store info for HVAC Sizing measure
253
- ptac.additionalProperties.setFeature(Constants.SizingInfoHVACCoolingCFMs, airflow_rate.to_s)
254
- ptac.additionalProperties.setFeature(Constants.SizingInfoHVACRatedCFMperTonCooling, cfms_ton_rated.join(','))
255
- ptac.additionalProperties.setFeature(Constants.SizingInfoHVACFracCoolLoadServed, cooling_system.fraction_cool_load_served)
256
- ptac.additionalProperties.setFeature(Constants.SizingInfoHVACCoolType, Constants.ObjectNameRoomAirConditioner)
257
183
  end
258
184
 
259
185
  def self.apply_evaporative_cooler(model, runner, cooling_system,
@@ -264,29 +190,28 @@ class HVAC
264
190
  obj_name = Constants.ObjectNameEvaporativeCooler
265
191
  sequential_cool_load_frac = calc_sequential_load_fraction(cooling_system.fraction_cool_load_served, remaining_cool_load_frac)
266
192
 
267
- # Evap Cooler
193
+ clg_ap = cooling_system.additional_properties
194
+ clg_cfm = cooling_system.cooling_airflow_cfm
268
195
 
196
+ # Evap Cooler
269
197
  evap_cooler = OpenStudio::Model::EvaporativeCoolerDirectResearchSpecial.new(model, model.alwaysOnDiscreteSchedule)
270
198
  evap_cooler.setName(obj_name)
271
- evap_cooler.setCoolerEffectiveness(0.72) # Assumed effectiveness
199
+ evap_cooler.setCoolerEffectiveness(clg_ap.effectiveness)
272
200
  evap_cooler.setEvaporativeOperationMinimumDrybulbTemperature(0) # relax limitation to open evap cooler for any potential cooling
273
201
  evap_cooler.setEvaporativeOperationMaximumLimitWetbulbTemperature(50) # relax limitation to open evap cooler for any potential cooling
274
202
  evap_cooler.setEvaporativeOperationMaximumLimitDrybulbTemperature(50) # relax limitation to open evap cooler for any potential cooling
203
+ evap_cooler.setPrimaryAirDesignFlowRate(UnitConversions.convert(clg_cfm, 'cfm', 'm^3/s'))
275
204
  hvac_map[cooling_system.id] << evap_cooler
276
205
 
277
206
  # Air Loop
278
-
279
- air_loop = create_air_loop(model, obj_name, evap_cooler, control_zone, 0, sequential_cool_load_frac)
280
- air_loop.additionalProperties.setFeature(Constants.SizingInfoHVACSystemIsDucted, !cooling_system.distribution_system_idref.nil?)
281
- air_loop.additionalProperties.setFeature(Constants.SizingInfoHVACCoolType, Constants.ObjectNameEvaporativeCooler)
207
+ air_loop = create_air_loop(model, obj_name, evap_cooler, control_zone, 0, sequential_cool_load_frac, clg_cfm)
282
208
  hvac_map[cooling_system.id] << air_loop
283
209
 
284
210
  # Fan
285
-
211
+ # Use VariableVolume object
286
212
  fan = OpenStudio::Model::FanVariableVolume.new(model, model.alwaysOnDiscreteSchedule)
287
213
  fan.setName(obj_name + ' supply fan')
288
214
  fan.setEndUseSubcategory('supply fan')
289
- fan.setFanEfficiency(1)
290
215
  fan.setMotorEfficiency(1)
291
216
  fan.setMotorInAirstreamFraction(0)
292
217
  fan.setFanPowerCoefficient1(0)
@@ -294,6 +219,9 @@ class HVAC
294
219
  fan.setFanPowerCoefficient3(0)
295
220
  fan.setFanPowerCoefficient4(0)
296
221
  fan.setFanPowerCoefficient5(0)
222
+ fan.setMaximumFlowRate(UnitConversions.convert(clg_cfm, 'cfm', 'm^3/s'))
223
+ fan_watts_per_cfm = [2.79 * clg_cfm**-0.29, 0.6].min # W/cfm; fit of efficacy to air flow from the CEC listed equipment
224
+ set_fan_power(fan, fan_watts_per_cfm)
297
225
  fan.addToNode(air_loop.supplyInletNode)
298
226
  hvac_map[cooling_system.id] += disaggregate_fan_or_pump(model, fan, nil, evap_cooler, nil)
299
227
 
@@ -303,6 +231,7 @@ class HVAC
303
231
  oa_intake_controller.setMinimumLimitType('FixedMinimum')
304
232
  oa_intake_controller.resetEconomizerMinimumLimitDryBulbTemperature
305
233
  oa_intake_controller.setMinimumFractionofOutdoorAirSchedule(model.alwaysOnDiscreteSchedule)
234
+ oa_intake_controller.setMaximumOutdoorAirFlowRate(UnitConversions.convert(clg_cfm, 'cfm', 'm^3/s'))
306
235
 
307
236
  oa_intake = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(model, oa_intake_controller)
308
237
  oa_intake.setName("#{air_loop.name} OA System")
@@ -315,10 +244,6 @@ class HVAC
315
244
  evap_stpt_manager.setReferenceTemperatureType('OutdoorAirWetBulb')
316
245
  evap_stpt_manager.setOffsetTemperatureDifference(0.0)
317
246
  evap_stpt_manager.addToNode(air_loop.supplyOutletNode)
318
-
319
- # Store info for HVAC Sizing measure
320
- evap_cooler.additionalProperties.setFeature(Constants.SizingInfoHVACFracCoolLoadServed, cooling_system.fraction_cool_load_served)
321
- evap_cooler.additionalProperties.setFeature(Constants.SizingInfoHVACCoolType, Constants.ObjectNameEvaporativeCooler)
322
247
  end
323
248
 
324
249
  def self.apply_central_air_to_air_heat_pump(model, runner, heat_pump,
@@ -330,205 +255,91 @@ class HVAC
330
255
  obj_name = Constants.ObjectNameAirSourceHeatPump
331
256
  sequential_heat_load_frac = calc_sequential_load_fraction(heat_pump.fraction_heat_load_served, remaining_heat_load_frac)
332
257
  sequential_cool_load_frac = calc_sequential_load_fraction(heat_pump.fraction_cool_load_served, remaining_cool_load_frac)
333
- if heat_pump.compressor_type == HPXML::HVACCompressorTypeSingleStage
334
- num_speeds = 1
335
- elsif heat_pump.compressor_type == HPXML::HVACCompressorTypeTwoStage
336
- num_speeds = 2
337
- elsif heat_pump.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
338
- num_speeds = 4
339
- end
340
- fan_power_rated = get_fan_power_rated(heat_pump.cooling_efficiency_seer)
341
- if heat_pump.fraction_heat_load_served <= 0
342
- crankcase_kw, crankcase_temp = 0, nil
343
- else
344
- crankcase_kw, crankcase_temp = get_crankcase_assumptions(heat_pump.fraction_cool_load_served)
345
- end
346
- hp_min_temp, supp_max_temp = get_heat_pump_temp_assumptions(heat_pump)
347
258
 
348
- # Cooling Coil
259
+ hp_ap = heat_pump.additional_properties
349
260
 
350
- cool_c_d = get_cool_c_d(num_speeds, heat_pump.cooling_efficiency_seer)
351
- if num_speeds == 1
352
- cool_rated_airflow_rate = 394.2 # cfm/ton
353
- cool_capacity_ratios = [1.0]
354
- cool_fan_speed_ratios = [1.0]
355
- cool_shrs = [heat_pump.cooling_shr]
356
- cool_cap_ft_spec = [[3.68637657, -0.098352478, 0.000956357, 0.005838141, -0.0000127, -0.000131702]]
357
- cool_eir_ft_spec = [[-3.437356399, 0.136656369, -0.001049231, -0.0079378, 0.000185435, -0.0001441]]
358
- cool_cap_fflow_spec = [[0.718664047, 0.41797409, -0.136638137]]
359
- cool_eir_fflow_spec = [[1.143487507, -0.13943972, -0.004047787]]
360
- cool_eers = [calc_eer_cooling_1speed(heat_pump.cooling_efficiency_seer, fan_power_rated, cool_eir_ft_spec)]
361
- elsif num_speeds == 2
362
- cool_rated_airflow_rate = 344.1 # cfm/ton
363
- cool_capacity_ratios = [0.72, 1.0]
364
- cool_fan_speed_ratios = [0.86, 1.0]
365
- cool_shrs = [heat_pump.cooling_shr - 0.014, heat_pump.cooling_shr] # TODO: is the following assumption correct (revisit Dylan's data?)? OR should value from HPXML be used for both stages?
366
- cool_cap_ft_spec = [[3.998418659, -0.108728222, 0.001056818, 0.007512314, -0.0000139, -0.000164716],
367
- [3.466810106, -0.091476056, 0.000901205, 0.004163355, -0.00000919, -0.000110829]]
368
- cool_eir_ft_spec = [[-4.282911381, 0.181023691, -0.001357391, -0.026310378, 0.000333282, -0.000197405],
369
- [-3.557757517, 0.112737397, -0.000731381, 0.013184877, 0.000132645, -0.000338716]]
370
- cool_cap_fflow_spec = [[0.655239515, 0.511655216, -0.166894731],
371
- [0.618281092, 0.569060264, -0.187341356]]
372
- cool_eir_fflow_spec = [[1.639108268, -0.998953996, 0.359845728],
373
- [1.570774717, -0.914152018, 0.343377302]]
374
- cool_eers = calc_eers_cooling_2speed(runner, heat_pump.cooling_efficiency_seer, cool_c_d, cool_capacity_ratios, cool_fan_speed_ratios, fan_power_rated, cool_eir_ft_spec, cool_cap_ft_spec, true)
375
- elsif num_speeds == 4
376
- cool_rated_airflow_rate = 411.0 # cfm/ton
377
- cool_capacity_ratios = [0.36, 0.51, 0.67, 1.0]
378
- cool_fan_speed_ratios = [0.42, 0.54, 0.68, 1.0]
379
- cool_shrs = [1.115, 1.026, 1.013, 1.0].map { |mult| heat_pump.cooling_shr * mult }
380
- # The following coefficients were generated using NREL experimental performance mapping for the Carrier unit
381
- cool_cap_coeff_perf_map = [[1.6516044444444447, 0.0698916049382716, -0.0005546296296296296, -0.08870160493827162, 0.0004135802469135802, 0.00029077160493827157],
382
- [-6.84948049382716, 0.26946, -0.0019413580246913577, -0.03281469135802469, 0.00015694444444444442, 3.32716049382716e-05],
383
- [-4.53543086419753, 0.15358543209876546, -0.0009345679012345678, 0.002666913580246914, -7.993827160493826e-06, -0.00011617283950617283],
384
- [-3.500948395061729, 0.11738987654320988, -0.0006580246913580248, 0.007003148148148148, -2.8518518518518517e-05, -0.0001284259259259259],
385
- [1.8769221728395058, -0.04768641975308643, 0.0006885802469135801, 0.006643395061728395, 1.4209876543209876e-05, -0.00024043209876543206]]
386
- cool_cap_ft_spec = cool_cap_coeff_perf_map.select { |i| [0, 1, 2, 4].include? cool_cap_coeff_perf_map.index(i) }
387
- cool_cap_ft_spec_3 = cool_cap_coeff_perf_map.select { |i| [0, 1, 4].include? cool_cap_coeff_perf_map.index(i) }
388
- cool_eir_coeff_perf_map = [[2.896298765432099, -0.12487654320987657, 0.0012148148148148148, 0.04492037037037037, 8.734567901234567e-05, -0.0006348765432098764],
389
- [6.428076543209876, -0.20913209876543212, 0.0018521604938271604, 0.024392592592592594, 0.00019691358024691356, -0.0006012345679012346],
390
- [5.136356049382716, -0.1591530864197531, 0.0014151234567901232, 0.018665555555555557, 0.00020398148148148147, -0.0005407407407407407],
391
- [1.3823471604938273, -0.02875123456790123, 0.00038302469135802463, 0.006344814814814816, 0.00024836419753086417, -0.00047469135802469134],
392
- [-1.0411735802469133, 0.055261604938271605, -0.0004404320987654321, 0.0002154938271604939, 0.00017484567901234564, -0.0002017901234567901]]
393
- cool_eir_ft_spec = cool_eir_coeff_perf_map.select { |i| [0, 1, 2, 4].include? cool_eir_coeff_perf_map.index(i) }
394
- cool_eir_ft_spec_3 = cool_eir_coeff_perf_map.select { |i| [0, 1, 4].include? cool_eir_coeff_perf_map.index(i) }
395
- cool_eir_fflow_spec = [[1, 0, 0]] * 4
396
- cool_cap_fflow_spec = [[1, 0, 0]] * 4
397
- cap_ratio_seer_3 = cool_capacity_ratios.select { |i| [0, 1, 3].include? cool_capacity_ratios.index(i) }
398
- fan_speed_seer_3 = cool_fan_speed_ratios.select { |i| [0, 1, 3].include? cool_fan_speed_ratios.index(i) }
399
- cool_eers = calc_eers_cooling_4speed(runner, heat_pump.cooling_efficiency_seer, cool_c_d, cap_ratio_seer_3, fan_speed_seer_3, fan_power_rated, cool_eir_ft_spec_3, cool_cap_ft_spec_3)
400
- end
401
- cool_cfms_ton_rated = calc_cfms_ton_rated(cool_rated_airflow_rate, cool_fan_speed_ratios, cool_capacity_ratios)
402
- cool_shrs_rated_gross = calc_shrs_rated_gross(num_speeds, cool_shrs, fan_power_rated, cool_cfms_ton_rated)
403
- cool_eirs = calc_cool_eirs(num_speeds, cool_eers, fan_power_rated)
404
- cool_closs_fplr_spec = [calc_plr_coefficients(cool_c_d)] * num_speeds
405
- clg_coil = create_dx_cooling_coil(model, obj_name, (0...num_speeds).to_a, cool_eirs, cool_cap_ft_spec, cool_eir_ft_spec, cool_closs_fplr_spec, cool_cap_fflow_spec, cool_eir_fflow_spec, cool_shrs_rated_gross, heat_pump.cooling_capacity, 0, nil, fan_power_rated)
261
+ # Cooling Coil
262
+ clg_coil = create_dx_cooling_coil(model, obj_name, heat_pump)
406
263
  hvac_map[heat_pump.id] << clg_coil
407
264
 
408
265
  # Heating Coil
409
-
410
- heat_c_d = get_heat_c_d(num_speeds, heat_pump.heating_efficiency_hspf)
411
- if num_speeds == 1
412
- heat_rated_airflow_rate = 384.1 # cfm/ton
413
- heat_capacity_ratios = [1.0]
414
- heat_fan_speed_ratios = [1.0]
415
- heat_eir_ft_spec = [[0.718398423, 0.003498178, 0.000142202, -0.005724331, 0.00014085, -0.000215321]]
416
- heat_cap_fflow_spec = [[0.694045465, 0.474207981, -0.168253446]]
417
- heat_eir_fflow_spec = [[2.185418751, -1.942827919, 0.757409168]]
418
- if heat_pump.heating_capacity_17F.nil?
419
- heat_cap_ft_spec = [[0.566333415, -0.000744164, -0.0000103, 0.009414634, 0.0000506, -0.00000675]]
420
- else
421
- heat_cap_ft_spec = calc_heat_cap_ft_spec_using_capacity_17F(num_speeds, heat_pump)
422
- end
423
- heat_cops = [calc_cop_heating_1speed(heat_pump.heating_efficiency_hspf, heat_c_d, fan_power_rated, heat_eir_ft_spec, heat_cap_ft_spec)]
424
- elsif num_speeds == 2
425
- heat_rated_airflow_rate = 352.2 # cfm/ton
426
- heat_capacity_ratios = [0.72, 1.0]
427
- heat_fan_speed_ratios = [0.8, 1.0]
428
- heat_eir_ft_spec = [[0.36338171, 0.013523725, 0.000258872, -0.009450269, 0.000439519, -0.000653723],
429
- [0.981100941, -0.005158493, 0.000243416, -0.005274352, 0.000230742, -0.000336954]]
430
- heat_cap_fflow_spec = [[0.741466907, 0.378645444, -0.119754733],
431
- [0.76634609, 0.32840943, -0.094701495]]
432
- heat_eir_fflow_spec = [[2.153618211, -1.737190609, 0.584269478],
433
- [2.001041353, -1.58869128, 0.587593517]]
434
- if heat_pump.heating_capacity_17F.nil?
435
- heat_cap_ft_spec = [[0.335690634, 0.002405123, -0.0000464, 0.013498735, 0.0000499, -0.00000725],
436
- [0.306358843, 0.005376987, -0.0000579, 0.011645092, 0.0000591, -0.0000203]]
437
- else
438
- heat_cap_ft_spec = calc_heat_cap_ft_spec_using_capacity_17F(num_speeds, heat_pump)
439
- end
440
- heat_cops = calc_cops_heating_2speed(heat_pump.heating_efficiency_hspf, heat_c_d, heat_capacity_ratios, heat_fan_speed_ratios, fan_power_rated, heat_eir_ft_spec, heat_cap_ft_spec)
441
- elsif num_speeds == 4
442
- heat_rated_airflow_rate = 296.9 # cfm/ton
443
- heat_capacity_ratios = [0.33, 0.56, 1.0, 1.17]
444
- heat_fan_speed_ratios = [0.63, 0.76, 1.0, 1.19]
445
- heat_eir_ft_spec = [[0.708311527, 0.020732093, 0.000391479, -0.037640031, 0.000979937, -0.001079042],
446
- [0.025480155, 0.020169585, 0.000121341, -0.004429789, 0.000166472, -0.00036447],
447
- [0.379003189, 0.014195012, 0.0000821046, -0.008894061, 0.000151519, -0.000210299],
448
- [0.690404655, 0.00616619, 0.000137643, -0.009350199, 0.000153427, -0.000213258]]
449
- heat_cap_fflow_spec = [[1, 0, 0]] * 4
450
- heat_eir_fflow_spec = [[1, 0, 0]] * 4
451
- if heat_pump.heating_capacity_17F.nil?
452
- heat_cap_ft_spec = [[0.304192655, -0.003972566, 0.0000196432, 0.024471251, -0.000000774126, -0.0000841323],
453
- [0.496381324, -0.00144792, 0.0, 0.016020855, 0.0000203447, -0.0000584118],
454
- [0.697171186, -0.006189599, 0.0000337077, 0.014291981, 0.0000105633, -0.0000387956],
455
- [0.555513805, -0.001337363, -0.00000265117, 0.014328826, 0.0000163849, -0.0000480711]]
456
- else
457
- heat_cap_ft_spec = calc_heat_cap_ft_spec_using_capacity_17F(num_speeds, heat_pump)
458
- end
459
- heat_cops = calc_cops_heating_4speed(runner, heat_pump.heating_efficiency_hspf, heat_c_d, heat_capacity_ratios, heat_fan_speed_ratios, fan_power_rated, heat_eir_ft_spec, heat_cap_ft_spec)
460
- end
461
- heat_cfms_ton_rated = calc_cfms_ton_rated(heat_rated_airflow_rate, heat_fan_speed_ratios, heat_capacity_ratios)
462
- heat_eirs = calc_heat_eirs(num_speeds, heat_cops, fan_power_rated)
463
- heat_closs_fplr_spec = [calc_plr_coefficients(heat_c_d)] * num_speeds
464
- htg_coil = create_dx_heating_coil(model, obj_name, (0...num_speeds).to_a, heat_eirs, heat_cap_ft_spec, heat_eir_ft_spec, heat_closs_fplr_spec, heat_cap_fflow_spec, heat_eir_fflow_spec, heat_pump.heating_capacity, crankcase_kw, crankcase_temp, fan_power_rated, hp_min_temp, heat_pump.fraction_heat_load_served)
266
+ htg_coil = create_dx_heating_coil(model, obj_name, heat_pump)
465
267
  hvac_map[heat_pump.id] << htg_coil
466
268
 
467
269
  # Supplemental Heating Coil
468
-
469
270
  htg_supp_coil = create_supp_heating_coil(model, obj_name, heat_pump)
470
271
  hvac_map[heat_pump.id] << htg_supp_coil
471
272
 
472
273
  # Fan
473
- fan_power_installed = get_fan_power_installed(heat_pump.cooling_efficiency_seer)
474
- fan = create_supply_fan(model, obj_name, num_speeds, fan_power_installed)
274
+ num_speeds = hp_ap.num_speeds
275
+ htg_cfm = heat_pump.heating_airflow_cfm
276
+ clg_cfm = heat_pump.cooling_airflow_cfm
277
+ fan_cfm = hp_ap.cool_fan_speed_ratios.max * [htg_cfm, clg_cfm].max
278
+ fan = create_supply_fan(model, obj_name, num_speeds, heat_pump.fan_watts_per_cfm, fan_cfm)
475
279
  hvac_map[heat_pump.id] += disaggregate_fan_or_pump(model, fan, htg_coil, clg_coil, htg_supp_coil)
476
280
 
477
281
  # Unitary System
478
-
479
- air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, supp_max_temp)
282
+ air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, htg_cfm, clg_cfm, hp_ap.supp_max_temp)
480
283
  hvac_map[heat_pump.id] << air_loop_unitary
481
284
 
285
+ # Unitary System Performance
482
286
  if num_speeds > 1
483
- # Unitary System Performance
484
287
  perf = OpenStudio::Model::UnitarySystemPerformanceMultispeed.new(model)
485
288
  perf.setSingleModeOperation(false)
486
289
  for speed in 1..num_speeds
487
- f = OpenStudio::Model::SupplyAirflowRatioField.new(heat_fan_speed_ratios[speed - 1], cool_fan_speed_ratios[speed - 1])
290
+ f = OpenStudio::Model::SupplyAirflowRatioField.new(hp_ap.heat_fan_speed_ratios[speed - 1], hp_ap.cool_fan_speed_ratios[speed - 1])
488
291
  perf.addSupplyAirflowRatioField(f)
489
292
  end
490
293
  air_loop_unitary.setDesignSpecificationMultispeedObject(perf)
491
294
  end
492
295
 
493
296
  # Air Loop
494
-
495
- air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_frac, sequential_cool_load_frac)
297
+ air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_frac, sequential_cool_load_frac, fan_cfm)
496
298
  hvac_map[heat_pump.id] << air_loop
497
299
 
498
- # Store info for HVAC Sizing measure
499
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACCapacityRatioHeating, heat_capacity_ratios.join(','))
500
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACCapacityRatioCooling, cool_capacity_ratios.join(','))
501
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACRatedCFMperTonHeating, heat_cfms_ton_rated.join(','))
502
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACRatedCFMperTonCooling, cool_cfms_ton_rated.join(','))
503
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACFracHeatLoadServed, heat_pump.fraction_heat_load_served)
504
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACFracCoolLoadServed, heat_pump.fraction_cool_load_served)
505
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACCoolType, Constants.ObjectNameAirSourceHeatPump)
506
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACHeatType, Constants.ObjectNameAirSourceHeatPump)
300
+ # HVAC Installation Quality
301
+ apply_installation_quality(model, heat_pump, heat_pump, air_loop_unitary, htg_coil, clg_coil, control_zone)
507
302
  end
508
303
 
509
304
  def self.apply_mini_split_air_conditioner(model, runner, cooling_system,
510
305
  remaining_cool_load_frac,
511
306
  control_zone, hvac_map)
512
307
 
513
- # Shoehorn cooling_system object into a corresponding heat_pump object
514
- heat_pump = HPXML::HeatPump.new(nil)
515
- heat_pump.id = cooling_system.id
516
- heat_pump.heat_pump_type = HPXML::HVACTypeHeatPumpMiniSplit
517
- heat_pump.heat_pump_fuel = cooling_system.cooling_system_fuel
518
- heat_pump.cooling_capacity = cooling_system.cooling_capacity
519
- if !heat_pump.cooling_capacity.nil?
520
- heat_pump.heating_capacity = 0
521
- end
522
- heat_pump.cooling_shr = cooling_system.cooling_shr
523
- heat_pump.fraction_heat_load_served = 0
524
- heat_pump.fraction_cool_load_served = cooling_system.fraction_cool_load_served
525
- heat_pump.cooling_efficiency_seer = cooling_system.cooling_efficiency_seer
526
- heat_pump.heating_efficiency_hspf = 7.7 # Arbitrary; shouldn't affect energy use TODO: Allow nil
527
- heat_pump.distribution_system_idref = cooling_system.distribution_system_idref
528
-
529
- apply_mini_split_heat_pump(model, runner, heat_pump, 0,
530
- remaining_cool_load_frac,
531
- control_zone, hvac_map)
308
+ hvac_map[cooling_system.id] = []
309
+ obj_name = Constants.ObjectNameMiniSplitAirConditioner
310
+ sequential_cool_load_frac = calc_sequential_load_fraction(cooling_system.fraction_cool_load_served, remaining_cool_load_frac)
311
+
312
+ clg_ap = cooling_system.additional_properties
313
+
314
+ # Cooling Coil
315
+ clg_coil = create_dx_cooling_coil(model, obj_name, cooling_system)
316
+ hvac_map[cooling_system.id] << clg_coil
317
+
318
+ # Fan
319
+ num_speeds = clg_ap.num_speeds
320
+ clg_cfm = cooling_system.cooling_airflow_cfm
321
+ fan = create_supply_fan(model, obj_name, num_speeds, cooling_system.fan_watts_per_cfm, clg_cfm)
322
+ hvac_map[cooling_system.id] += disaggregate_fan_or_pump(model, fan, nil, clg_coil, nil)
323
+
324
+ # Unitary System
325
+ air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, nil, clg_coil, nil, nil, clg_cfm)
326
+ hvac_map[cooling_system.id] << air_loop_unitary
327
+
328
+ # Unitary System Performance
329
+ perf = OpenStudio::Model::UnitarySystemPerformanceMultispeed.new(model)
330
+ perf.setSingleModeOperation(false)
331
+ for i in 0..(num_speeds - 1)
332
+ f = OpenStudio::Model::SupplyAirflowRatioField.new(1.0, clg_ap.cool_fan_speed_ratios[i])
333
+ perf.addSupplyAirflowRatioField(f)
334
+ end
335
+ air_loop_unitary.setDesignSpecificationMultispeedObject(perf)
336
+
337
+ # Air Loop
338
+ air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, 0, sequential_cool_load_frac, clg_cfm)
339
+ hvac_map[cooling_system.id] << air_loop
340
+
341
+ # HVAC Installation Quality
342
+ apply_installation_quality(model, nil, cooling_system, air_loop_unitary, nil, clg_coil, control_zone)
532
343
  end
533
344
 
534
345
  def self.apply_mini_split_heat_pump(model, runner, heat_pump,
@@ -540,197 +351,48 @@ class HVAC
540
351
  obj_name = Constants.ObjectNameMiniSplitHeatPump
541
352
  sequential_heat_load_frac = calc_sequential_load_fraction(heat_pump.fraction_heat_load_served, remaining_heat_load_frac)
542
353
  sequential_cool_load_frac = calc_sequential_load_fraction(heat_pump.fraction_cool_load_served, remaining_cool_load_frac)
543
- num_speeds = 10
544
- mshp_indices = [1, 3, 5, 9]
545
- hp_min_temp, supp_max_temp = get_heat_pump_temp_assumptions(heat_pump)
546
- fan_power_installed = 0.07 # W/cfm
547
- pan_heater_power = 0.0 # W, disabled
548
-
549
- # Calculate generic inputs
550
- min_cooling_capacity = 0.4 # frac
551
- max_cooling_capacity = 1.2 # frac
552
- min_cooling_airflow_rate = 200.0
553
- max_cooling_airflow_rate = 425.0
554
- min_heating_capacity = 0.3 # frac
555
- max_heating_capacity = 1.2 # frac
556
- min_heating_airflow_rate = 200.0
557
- max_heating_airflow_rate = 400.0
558
- if heat_pump.heating_capacity.nil?
559
- heating_capacity_offset = 2300.0 # Btu/hr
560
- else
561
- heating_capacity_offset = heat_pump.heating_capacity - heat_pump.cooling_capacity
562
- end
563
- if heat_pump.heating_capacity_17F.nil?
564
- cap_retention_frac = 0.25 # frac
565
- cap_retention_temp = -5.0 # deg-F
566
- else
567
- cap_retention_frac = heat_pump.heating_capacity_17F / heat_pump.heating_capacity
568
- cap_retention_temp = 17.0 # deg-F
569
- end
570
354
 
571
- # Cooling Coil
355
+ hp_ap = heat_pump.additional_properties
572
356
 
573
- cool_cap_ft_spec = [[0.7531983499655835, 0.003618193903031667, 0.0, 0.006574385031351544, -6.87181191015432e-05, 0.0]] * num_speeds
574
- cool_eir_ft_spec = [[-0.06376924779982301, -0.0013360593470367282, 1.413060577993827e-05, 0.019433076486584752, -4.91395947154321e-05, -4.909341249475308e-05]] * num_speeds
575
- cool_cap_fflow_spec = [[1, 0, 0]] * num_speeds
576
- cool_eir_fflow_spec = [[1, 0, 0]] * num_speeds
577
- cool_c_d = get_cool_c_d(num_speeds, heat_pump.cooling_efficiency_seer)
578
- cool_closs_fplr_spec = [calc_plr_coefficients(cool_c_d)] * num_speeds
579
- dB_rated = 80.0 # deg-F
580
- wB_rated = 67.0 # deg-F
581
- cool_cfms_ton_rated, cool_capacity_ratios, cool_shrs_rated_gross = calc_mshp_cfms_ton_cooling(min_cooling_capacity, max_cooling_capacity, min_cooling_airflow_rate, max_cooling_airflow_rate, num_speeds, dB_rated, wB_rated, heat_pump.cooling_shr)
582
- cool_eirs = calc_mshp_cool_eirs(runner, heat_pump.cooling_efficiency_seer, fan_power_installed, cool_c_d, num_speeds, cool_capacity_ratios, cool_cfms_ton_rated, cool_eir_ft_spec, cool_cap_ft_spec)
583
- clg_coil = create_dx_cooling_coil(model, obj_name, mshp_indices, cool_eirs, cool_cap_ft_spec, cool_eir_ft_spec, cool_closs_fplr_spec, cool_cap_fflow_spec, cool_eir_fflow_spec, cool_shrs_rated_gross, heat_pump.cooling_capacity, 0.0, nil, nil)
357
+ # Cooling Coil
358
+ clg_coil = create_dx_cooling_coil(model, obj_name, heat_pump)
584
359
  hvac_map[heat_pump.id] << clg_coil
585
360
 
586
361
  # Heating Coil
587
-
588
- # cop/eir as a function of temperature
589
- # Generic curves (=Daikin from lab data)
590
- heat_eir_ft_spec = [[0.9999941697687026, 0.004684593830254383, 5.901286675833333e-05, -0.0028624467783091973, 1.3041120194135802e-05, -0.00016172918478765433]] * num_speeds
591
- heat_cap_fflow_spec = [[1, 0, 0]] * num_speeds
592
- heat_eir_fflow_spec = [[1, 0, 0]] * num_speeds
593
-
594
- # Derive coefficients from user input for capacity retention at outdoor drybulb temperature X [C].
595
- # Biquadratic: capacity multiplier = a + b*IAT + c*IAT^2 + d*OAT + e*OAT^2 + f*IAT*OAT
596
- x_A = UnitConversions.convert(cap_retention_temp, 'F', 'C')
597
- y_A = cap_retention_frac
598
- x_B = UnitConversions.convert(47.0, 'F', 'C') # 47F is the rating point
599
- y_B = 1.0 # Maximum capacity factor is 1 at the rating point, by definition (this is maximum capacity, not nominal capacity)
600
- oat_slope = (y_B - y_A) / (x_B - x_A)
601
- oat_intercept = y_A - (x_A * oat_slope)
602
-
603
- # Coefficients for the indoor temperature relationship are retained from the generic curve (Daikin lab data).
604
- iat_slope = -0.010386676170938
605
- iat_intercept = 0.219274275
606
- a = oat_intercept + iat_intercept
607
- b = iat_slope
608
- c = 0
609
- d = oat_slope
610
- e = 0
611
- f = 0
612
- heat_cap_ft_spec = [convert_curve_biquadratic([a, b, c, d, e, f], false)] * num_speeds
613
-
614
- heat_c_d = get_heat_c_d(num_speeds, heat_pump.heating_efficiency_hspf)
615
- heat_closs_fplr_spec = [calc_plr_coefficients(heat_c_d)] * num_speeds
616
- heat_cfms_ton_rated, heat_capacity_ratios = calc_mshp_cfms_ton_heating(min_heating_capacity, max_heating_capacity, min_heating_airflow_rate, max_heating_airflow_rate, num_speeds)
617
- heat_eirs = calc_mshp_heat_eirs(runner, heat_pump.heating_efficiency_hspf, fan_power_installed, hp_min_temp, heat_c_d, cool_cfms_ton_rated, num_speeds, heat_capacity_ratios, heat_cfms_ton_rated, heat_eir_ft_spec, heat_cap_ft_spec)
618
- htg_coil = create_dx_heating_coil(model, obj_name, mshp_indices, heat_eirs, heat_cap_ft_spec, heat_eir_ft_spec, heat_closs_fplr_spec, heat_cap_fflow_spec, heat_eir_fflow_spec, heat_pump.heating_capacity, 0.0, nil, nil, hp_min_temp, heat_pump.fraction_heat_load_served)
362
+ htg_coil = create_dx_heating_coil(model, obj_name, heat_pump)
619
363
  hvac_map[heat_pump.id] << htg_coil
620
364
 
621
365
  # Supplemental Heating Coil
622
-
623
366
  htg_supp_coil = create_supp_heating_coil(model, obj_name, heat_pump)
624
367
  hvac_map[heat_pump.id] << htg_supp_coil
625
368
 
626
369
  # Fan
627
- fan_power_curve = create_curve_exponent(model, [0, 1, 3], obj_name + ' fan power curve', -100, 100)
628
- fan_eff_curve = create_curve_cubic(model, [0, 1, 0, 0], obj_name + ' fan eff curve', 0, 1, 0.01, 1)
629
- fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule, fan_power_curve, fan_eff_curve)
630
- fan_eff = UnitConversions.convert(UnitConversions.convert(0.1, 'inH2O', 'Pa') / fan_power_installed, 'cfm', 'm^3/s') # Overall Efficiency of the Fan, Motor and Drive
631
- fan.setName(obj_name + ' supply fan')
632
- fan.setEndUseSubcategory('supply fan')
633
- fan.setFanEfficiency(fan_eff)
634
- fan.setPressureRise(calc_fan_pressure_rise(fan_eff, fan_power_installed))
635
- fan.setMotorEfficiency(1.0)
636
- fan.setMotorInAirstreamFraction(1.0)
370
+ num_speeds = hp_ap.num_speeds
371
+ htg_cfm = heat_pump.heating_airflow_cfm
372
+ clg_cfm = heat_pump.cooling_airflow_cfm
373
+ fan_cfm = hp_ap.cool_fan_speed_ratios.max * [htg_cfm, clg_cfm].max
374
+ fan = create_supply_fan(model, obj_name, num_speeds, heat_pump.fan_watts_per_cfm, fan_cfm)
637
375
  hvac_map[heat_pump.id] += disaggregate_fan_or_pump(model, fan, htg_coil, clg_coil, htg_supp_coil)
638
376
 
639
377
  # Unitary System
640
-
641
- air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, supp_max_temp)
378
+ air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, htg_cfm, clg_cfm, hp_ap.supp_max_temp)
642
379
  hvac_map[heat_pump.id] << air_loop_unitary
643
380
 
381
+ # Unitary System Performance
644
382
  perf = OpenStudio::Model::UnitarySystemPerformanceMultispeed.new(model)
645
383
  perf.setSingleModeOperation(false)
646
- mshp_indices.each do |mshp_index|
647
- ratio_heating = heat_cfms_ton_rated[mshp_index] / heat_cfms_ton_rated[mshp_indices[-1]]
648
- ratio_cooling = cool_cfms_ton_rated[mshp_index] / cool_cfms_ton_rated[mshp_indices[-1]]
649
- f = OpenStudio::Model::SupplyAirflowRatioField.new(ratio_heating, ratio_cooling)
384
+ for i in 0..(num_speeds - 1)
385
+ f = OpenStudio::Model::SupplyAirflowRatioField.new(hp_ap.heat_fan_speed_ratios[i], hp_ap.cool_fan_speed_ratios[i])
650
386
  perf.addSupplyAirflowRatioField(f)
651
387
  end
652
388
  air_loop_unitary.setDesignSpecificationMultispeedObject(perf)
653
389
 
654
390
  # Air Loop
655
-
656
- air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_frac, sequential_cool_load_frac)
391
+ air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_frac, sequential_cool_load_frac, fan_cfm)
657
392
  hvac_map[heat_pump.id] << air_loop
658
393
 
659
- if pan_heater_power > 0
660
-
661
- mshp_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Heating Coil Electric Energy')
662
- mshp_sensor.setName("#{obj_name} vrf energy sensor")
663
- mshp_sensor.setKeyName(obj_name + ' coil')
664
-
665
- equip_def = OpenStudio::Model::ElectricEquipmentDefinition.new(model)
666
- equip_def.setName(obj_name + ' pan heater equip')
667
- equip = OpenStudio::Model::ElectricEquipment.new(equip_def)
668
- equip.setName(equip_def.name.to_s)
669
- equip.setSpace(control_zone.spaces[0])
670
- equip_def.setFractionRadiant(0)
671
- equip_def.setFractionLatent(0)
672
- equip_def.setFractionLost(1)
673
- equip.setSchedule(model.alwaysOnDiscreteSchedule)
674
- equip.setEndUseSubcategory(obj_name + ' pan heater')
675
-
676
- pan_heater_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(equip, 'ElectricEquipment', 'Electric Power Level')
677
- pan_heater_actuator.setName("#{obj_name} pan heater actuator")
678
-
679
- tout_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Outdoor Air Drybulb Temperature')
680
- tout_sensor.setName("#{obj_name} tout sensor")
681
- thermal_zones.each do |thermal_zone|
682
- if Geometry.is_living(thermal_zone)
683
- tout_sensor.setKeyName(thermal_zone.name.to_s)
684
- break
685
- end
686
- end
687
-
688
- program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
689
- program.setName(obj_name + ' pan heater program')
690
- if not heat_pump.cooling_capacity.nil?
691
- num_outdoor_units = (UnitConversions.convert([heat_pump.cooling_capacity, Constants.small].max, 'Btu/hr', 'ton') / 1.5).ceil # Assume 1.5 tons max per outdoor unit
692
- else
693
- num_outdoor_units = 2
694
- end
695
- pan_heater_power *= num_outdoor_units # W
696
- program.addLine("Set #{pan_heater_actuator.name} = 0")
697
- program.addLine("If #{mshp_sensor.name} > 0")
698
- program.addLine(" If #{tout_sensor.name} <= #{UnitConversions.convert(32.0, 'F', 'C').round(3)}")
699
- program.addLine(" Set #{pan_heater_actuator.name} = #{pan_heater_power}")
700
- program.addLine(' EndIf')
701
- program.addLine('EndIf')
702
-
703
- program_calling_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
704
- program_calling_manager.setName(obj_name + ' pan heater program calling manager')
705
- program_calling_manager.setCallingPoint('BeginTimestepBeforePredictor')
706
- program_calling_manager.addProgram(program)
707
-
708
- end
709
-
710
- # Store info for HVAC Sizing measure
711
- heat_capacity_ratios_4 = []
712
- cool_capacity_ratios_4 = []
713
- heat_cfms_ton_rated_4 = []
714
- cool_cfms_ton_rated_4 = []
715
- cool_shrs_rated_gross_4 = []
716
- mshp_indices.each do |mshp_index|
717
- heat_capacity_ratios_4 << heat_capacity_ratios[mshp_index]
718
- cool_capacity_ratios_4 << cool_capacity_ratios[mshp_index]
719
- heat_cfms_ton_rated_4 << heat_cfms_ton_rated[mshp_index]
720
- cool_cfms_ton_rated_4 << cool_cfms_ton_rated[mshp_index]
721
- cool_shrs_rated_gross_4 << cool_shrs_rated_gross[mshp_index]
722
- end
723
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACSystemIsDucted, !heat_pump.distribution_system_idref.nil?)
724
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACCapacityRatioHeating, heat_capacity_ratios_4.join(','))
725
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACCapacityRatioCooling, cool_capacity_ratios_4.join(','))
726
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACHeatingCFMs, heat_cfms_ton_rated_4.join(','))
727
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACCoolingCFMs, cool_cfms_ton_rated_4.join(','))
728
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACHeatingCapacityOffset, heating_capacity_offset)
729
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACFracHeatLoadServed, heat_pump.fraction_heat_load_served)
730
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACFracCoolLoadServed, heat_pump.fraction_cool_load_served)
731
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACSHR, cool_shrs_rated_gross_4.join(','))
732
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACCoolType, Constants.ObjectNameMiniSplitHeatPump)
733
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACHeatType, Constants.ObjectNameMiniSplitHeatPump)
394
+ # HVAC Installation Quality
395
+ apply_installation_quality(model, heat_pump, heat_pump, air_loop_unitary, htg_coil, clg_coil, control_zone)
734
396
  end
735
397
 
736
398
  def self.apply_ground_to_air_heat_pump(model, runner, weather, heat_pump,
@@ -741,181 +403,101 @@ class HVAC
741
403
  obj_name = Constants.ObjectNameGroundSourceHeatPump
742
404
  sequential_heat_load_frac = calc_sequential_load_fraction(heat_pump.fraction_heat_load_served, remaining_heat_load_frac)
743
405
  sequential_cool_load_frac = calc_sequential_load_fraction(heat_pump.fraction_cool_load_served, remaining_cool_load_frac)
744
- pipe_cond = 0.23 # Pipe thermal conductivity, default to high density polyethylene
745
- ground_conductivity = 0.6
746
- grout_conductivity = 0.4
747
- bore_config = nil # Autosize
748
- bore_holes = nil # Autosize
749
- bore_depth = nil # Autosize
750
- bore_spacing = 20.0
751
- bore_diameter = 5.0
752
- pipe_size = 0.75
753
- ground_diffusivity = 0.0208
754
- fluid_type = Constants.FluidPropyleneGlycol
755
- frac_glycol = 0.3
756
- design_delta_t = 10.0
757
- chw_design = [85.0, weather.design.CoolingDrybulb - 15.0, weather.data.AnnualAvgDrybulb + 10.0].max # Temperature of water entering indoor coil,use 85F as lower bound
758
- if fluid_type == Constants.FluidWater
759
- hw_design = [45.0, weather.design.HeatingDrybulb + 35.0, weather.data.AnnualAvgDrybulb - 10.0].max # Temperature of fluid entering indoor coil, use 45F as lower bound for water
760
- else
761
- hw_design = [35.0, weather.design.HeatingDrybulb + 35.0, weather.data.AnnualAvgDrybulb - 10.0].min # Temperature of fluid entering indoor coil, use 35F as upper bound
762
- end
763
- # Pipe nominal size conversion to pipe outside diameter and inside diameter,
764
- # only pipe sizes <= 2" are used here with DR11 (dimension ratio),
765
- if pipe_size == 0.75 # 3/4" pipe
766
- pipe_od = 1.050
767
- pipe_id = 0.859
768
- elsif pipe_size == 1.0 # 1" pipe
769
- pipe_od = 1.315
770
- pipe_id = 1.076
771
- elsif pipe_size == 1.25 # 1-1/4" pipe
772
- pipe_od = 1.660
773
- pipe_id = 1.358
774
- end
775
- u_tube_spacing_type = 'b'
776
- # Calculate distance between pipes
777
- if u_tube_spacing_type == 'as'
778
- # Two tubes, spaced 1/8” apart at the center of the borehole
779
- u_tube_spacing = 0.125
780
- elsif u_tube_spacing_type == 'b'
781
- # Two tubes equally spaced between the borehole edges
782
- u_tube_spacing = 0.9661
783
- elsif u_tube_spacing_type == 'c'
784
- # Both tubes placed against outer edge of borehole
785
- u_tube_spacing = bore_diameter - 2 * pipe_od
786
- end
787
- shank_spacing = u_tube_spacing + pipe_od # Distance from center of pipe to center of pipe
788
406
 
789
- if frac_glycol == 0
790
- fluid_type = Constants.FluidWater
791
- runner.registerWarning("Specified #{fluid_type} fluid type and 0 fraction of glycol, so assuming #{Constants.FluidWater} fluid type.")
407
+ hp_ap = heat_pump.additional_properties
408
+ htg_cfm = heat_pump.heating_airflow_cfm
409
+ clg_cfm = heat_pump.cooling_airflow_cfm
410
+
411
+ if hp_ap.frac_glycol == 0
412
+ hp_ap.fluid_type = Constants.FluidWater
413
+ runner.registerWarning("Specified #{hp_ap.fluid_type} fluid type and 0 fraction of glycol, so assuming #{Constants.FluidWater} fluid type.")
792
414
  end
793
415
 
794
416
  # Cooling Coil
795
-
796
- coil_bf = 0.08060000
797
- cool_cap_ft_spec = [0.39039063, 0.01382596, 0.00000000, -0.00445738, 0.00000000, 0.00000000]
798
- cool_SH_ft_spec = [4.27136253, -0.04678521, 0.00000000, -0.00219031, 0.00000000, 0.00000000]
799
- cool_power_ft_spec = [0.01717338, 0.00316077, 0.00000000, 0.01043792, 0.00000000, 0.00000000]
800
- coil_bf_ft_spec = [1.21005458, -0.00664200, 0.00000000, 0.00348246, 0.00000000, 0.00000000]
801
- gshp_cool_cap_fT_coeff = convert_curve_gshp(cool_cap_ft_spec, false)
802
- gshp_cool_power_fT_coeff = convert_curve_gshp(cool_power_ft_spec, false)
803
- gshp_cool_SH_fT_coeff = convert_curve_gshp(cool_SH_ft_spec, false)
804
-
805
- # FUTURE: Reconcile these adjustments with ANSI/RESNET/ICC 301-2019 Section 4.4.5
806
- fan_adjust_kw = UnitConversions.convert(400.0, 'Btu/hr', 'ton') * UnitConversions.convert(1.0, 'cfm', 'm^3/s') * 1000.0 * 0.35 * 249.0 / 300.0 # Adjustment per ISO 13256-1 Internal pressure drop across heat pump assumed to be 0.5 in. w.g.
807
- pump_adjust_kw = UnitConversions.convert(3.0, 'Btu/hr', 'ton') * UnitConversions.convert(1.0, 'gal/min', 'm^3/s') * 1000.0 * 6.0 * 2990.0 / 3000.0 # Adjustment per ISO 13256-1 Internal Pressure drop across heat pump coil assumed to be 11ft w.g.
808
- cooling_eir = UnitConversions.convert((1.0 - heat_pump.cooling_efficiency_eer * (fan_adjust_kw + pump_adjust_kw)) / (heat_pump.cooling_efficiency_eer * (1.0 + UnitConversions.convert(fan_adjust_kw, 'Wh', 'Btu'))), 'Wh', 'Btu')
809
-
810
- clg_coil = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit.new(model)
417
+ clg_total_cap_curve = create_curve_quad_linear(model, hp_ap.cool_cap_ft_spec[0], obj_name + ' clg total cap curve')
418
+ clg_sens_cap_curve = create_curve_quint_linear(model, hp_ap.cool_sh_ft_spec[0], obj_name + ' clg sens cap curve')
419
+ clg_power_curve = create_curve_quad_linear(model, hp_ap.cool_power_ft_spec[0], obj_name + ' clg power curve')
420
+ clg_coil = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit.new(model, clg_total_cap_curve, clg_sens_cap_curve, clg_power_curve)
811
421
  clg_coil.setName(obj_name + ' clg coil')
812
- if not heat_pump.cooling_capacity.nil?
813
- clg_coil.setRatedTotalCoolingCapacity(UnitConversions.convert([heat_pump.cooling_capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
814
- end
815
- clg_coil.setRatedCoolingCoefficientofPerformance(1.0 / cooling_eir)
816
- clg_coil.setTotalCoolingCapacityCoefficient1(gshp_cool_cap_fT_coeff[0])
817
- clg_coil.setTotalCoolingCapacityCoefficient2(gshp_cool_cap_fT_coeff[1])
818
- clg_coil.setTotalCoolingCapacityCoefficient3(gshp_cool_cap_fT_coeff[2])
819
- clg_coil.setTotalCoolingCapacityCoefficient4(gshp_cool_cap_fT_coeff[3])
820
- clg_coil.setTotalCoolingCapacityCoefficient5(gshp_cool_cap_fT_coeff[4])
821
- clg_coil.setSensibleCoolingCapacityCoefficient1(gshp_cool_SH_fT_coeff[0])
822
- clg_coil.setSensibleCoolingCapacityCoefficient2(0)
823
- clg_coil.setSensibleCoolingCapacityCoefficient3(gshp_cool_SH_fT_coeff[1])
824
- clg_coil.setSensibleCoolingCapacityCoefficient4(gshp_cool_SH_fT_coeff[2])
825
- clg_coil.setSensibleCoolingCapacityCoefficient5(gshp_cool_SH_fT_coeff[3])
826
- clg_coil.setSensibleCoolingCapacityCoefficient6(gshp_cool_SH_fT_coeff[4])
827
- clg_coil.setCoolingPowerConsumptionCoefficient1(gshp_cool_power_fT_coeff[0])
828
- clg_coil.setCoolingPowerConsumptionCoefficient2(gshp_cool_power_fT_coeff[1])
829
- clg_coil.setCoolingPowerConsumptionCoefficient3(gshp_cool_power_fT_coeff[2])
830
- clg_coil.setCoolingPowerConsumptionCoefficient4(gshp_cool_power_fT_coeff[3])
831
- clg_coil.setCoolingPowerConsumptionCoefficient5(gshp_cool_power_fT_coeff[4])
422
+ clg_coil.setRatedCoolingCoefficientofPerformance(1.0 / hp_ap.cool_rated_eirs[0])
832
423
  clg_coil.setNominalTimeforCondensateRemovaltoBegin(1000)
833
424
  clg_coil.setRatioofInitialMoistureEvaporationRateandSteadyStateLatentCapacity(1.5)
425
+ clg_coil.setRatedAirFlowRate(UnitConversions.convert(clg_cfm, 'cfm', 'm^3/s'))
426
+ clg_coil.setRatedWaterFlowRate(UnitConversions.convert(hp_ap.GSHP_Loop_flow, 'gal/min', 'm^3/s'))
427
+ clg_coil.setRatedTotalCoolingCapacity(UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'W'))
428
+ clg_coil.setRatedSensibleCoolingCapacity(UnitConversions.convert(hp_ap.cooling_capacity_sensible, 'Btu/hr', 'W'))
834
429
  hvac_map[heat_pump.id] << clg_coil
835
430
 
836
431
  # Heating Coil
837
-
838
- heat_cap_ft_spec = [0.67104926, -0.00210834, 0.00000000, 0.01491424, 0.00000000, 0.00000000]
839
- heat_power_ft_spec = [-0.46308105, 0.02008988, 0.00000000, 0.00300222, 0.00000000, 0.00000000]
840
- gshp_heat_cap_fT_coeff = convert_curve_gshp(heat_cap_ft_spec, false)
841
- gshp_heat_power_fT_coeff = convert_curve_gshp(heat_power_ft_spec, false)
842
-
843
- heating_eir = (1.0 - heat_pump.heating_efficiency_cop * (fan_adjust_kw + pump_adjust_kw)) / (heat_pump.heating_efficiency_cop * (1.0 - fan_adjust_kw))
844
-
845
- htg_coil = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit.new(model)
432
+ htg_cap_curve = create_curve_quad_linear(model, hp_ap.heat_cap_ft_spec[0], obj_name + ' htg cap curve')
433
+ htg_power_curve = create_curve_quad_linear(model, hp_ap.heat_power_ft_spec[0], obj_name + ' htg power curve')
434
+ htg_coil = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit.new(model, htg_cap_curve, htg_power_curve)
846
435
  htg_coil.setName(obj_name + ' htg coil')
847
- if not heat_pump.heating_capacity.nil?
848
- htg_coil.setRatedHeatingCapacity(UnitConversions.convert([heat_pump.heating_capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
849
- end
850
- htg_coil.setRatedHeatingCoefficientofPerformance(1.0 / heating_eir)
851
- htg_coil.setHeatingCapacityCoefficient1(gshp_heat_cap_fT_coeff[0])
852
- htg_coil.setHeatingCapacityCoefficient2(gshp_heat_cap_fT_coeff[1])
853
- htg_coil.setHeatingCapacityCoefficient3(gshp_heat_cap_fT_coeff[2])
854
- htg_coil.setHeatingCapacityCoefficient4(gshp_heat_cap_fT_coeff[3])
855
- htg_coil.setHeatingCapacityCoefficient5(gshp_heat_cap_fT_coeff[4])
856
- htg_coil.setHeatingPowerConsumptionCoefficient1(gshp_heat_power_fT_coeff[0])
857
- htg_coil.setHeatingPowerConsumptionCoefficient2(gshp_heat_power_fT_coeff[1])
858
- htg_coil.setHeatingPowerConsumptionCoefficient3(gshp_heat_power_fT_coeff[2])
859
- htg_coil.setHeatingPowerConsumptionCoefficient4(gshp_heat_power_fT_coeff[3])
860
- htg_coil.setHeatingPowerConsumptionCoefficient5(gshp_heat_power_fT_coeff[4])
436
+ htg_coil.setRatedHeatingCoefficientofPerformance(1.0 / hp_ap.heat_rated_eirs[0])
437
+ htg_coil.setRatedAirFlowRate(UnitConversions.convert(htg_cfm, 'cfm', 'm^3/s'))
438
+ htg_coil.setRatedWaterFlowRate(UnitConversions.convert(hp_ap.GSHP_Loop_flow, 'gal/min', 'm^3/s'))
439
+ htg_coil.setRatedHeatingCapacity(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W'))
861
440
  hvac_map[heat_pump.id] << htg_coil
862
441
 
863
442
  # Supplemental Heating Coil
864
-
865
443
  htg_supp_coil = create_supp_heating_coil(model, obj_name, heat_pump)
866
444
  hvac_map[heat_pump.id] << htg_supp_coil
867
445
 
868
446
  # Ground Heat Exchanger
869
-
870
447
  ground_heat_exch_vert = OpenStudio::Model::GroundHeatExchangerVertical.new(model)
871
448
  ground_heat_exch_vert.setName(obj_name + ' exchanger')
872
- ground_heat_exch_vert.setBoreHoleRadius(UnitConversions.convert(bore_diameter / 2.0, 'in', 'm'))
873
- ground_heat_exch_vert.setGroundThermalConductivity(UnitConversions.convert(ground_conductivity, 'Btu/(hr*ft*R)', 'W/(m*K)'))
874
- ground_heat_exch_vert.setGroundThermalHeatCapacity(UnitConversions.convert(ground_conductivity / ground_diffusivity, 'Btu/(ft^3*F)', 'J/(m^3*K)'))
449
+ ground_heat_exch_vert.setBoreHoleRadius(UnitConversions.convert(hp_ap.bore_diameter / 2.0, 'in', 'm'))
450
+ ground_heat_exch_vert.setGroundThermalConductivity(UnitConversions.convert(hp_ap.ground_conductivity, 'Btu/(hr*ft*R)', 'W/(m*K)'))
451
+ ground_heat_exch_vert.setGroundThermalHeatCapacity(UnitConversions.convert(hp_ap.ground_conductivity / hp_ap.ground_diffusivity, 'Btu/(ft^3*F)', 'J/(m^3*K)'))
875
452
  ground_heat_exch_vert.setGroundTemperature(UnitConversions.convert(weather.data.AnnualAvgDrybulb, 'F', 'C'))
876
- ground_heat_exch_vert.setGroutThermalConductivity(UnitConversions.convert(grout_conductivity, 'Btu/(hr*ft*R)', 'W/(m*K)'))
877
- ground_heat_exch_vert.setPipeThermalConductivity(UnitConversions.convert(pipe_cond, 'Btu/(hr*ft*R)', 'W/(m*K)'))
878
- ground_heat_exch_vert.setPipeOutDiameter(UnitConversions.convert(pipe_od, 'in', 'm'))
879
- ground_heat_exch_vert.setUTubeDistance(UnitConversions.convert(shank_spacing, 'in', 'm'))
880
- ground_heat_exch_vert.setPipeThickness(UnitConversions.convert((pipe_od - pipe_id) / 2.0, 'in', 'm'))
453
+ ground_heat_exch_vert.setGroutThermalConductivity(UnitConversions.convert(hp_ap.grout_conductivity, 'Btu/(hr*ft*R)', 'W/(m*K)'))
454
+ ground_heat_exch_vert.setPipeThermalConductivity(UnitConversions.convert(hp_ap.pipe_cond, 'Btu/(hr*ft*R)', 'W/(m*K)'))
455
+ ground_heat_exch_vert.setPipeOutDiameter(UnitConversions.convert(hp_ap.pipe_od, 'in', 'm'))
456
+ ground_heat_exch_vert.setUTubeDistance(UnitConversions.convert(hp_ap.shank_spacing, 'in', 'm'))
457
+ ground_heat_exch_vert.setPipeThickness(UnitConversions.convert((hp_ap.pipe_od - hp_ap.pipe_id) / 2.0, 'in', 'm'))
881
458
  ground_heat_exch_vert.setMaximumLengthofSimulation(1)
882
459
  ground_heat_exch_vert.setGFunctionReferenceRatio(0.0005)
460
+ ground_heat_exch_vert.setDesignFlowRate(UnitConversions.convert(hp_ap.GSHP_Loop_flow, 'gal/min', 'm^3/s'))
461
+ ground_heat_exch_vert.setNumberofBoreHoles(hp_ap.GSHP_Bore_Holes.to_i)
462
+ ground_heat_exch_vert.setBoreHoleLength(UnitConversions.convert(hp_ap.GSHP_Bore_Depth, 'ft', 'm'))
463
+ ground_heat_exch_vert.removeAllGFunctions
464
+ for i in 0..(hp_ap.GSHP_G_Functions[0].size - 1)
465
+ ground_heat_exch_vert.addGFunction(hp_ap.GSHP_G_Functions[0][i], hp_ap.GSHP_G_Functions[1][i])
466
+ end
883
467
 
884
468
  # Plant Loop
885
-
886
469
  plant_loop = OpenStudio::Model::PlantLoop.new(model)
887
470
  plant_loop.setName(obj_name + ' condenser loop')
888
- if fluid_type == Constants.FluidWater
471
+ if hp_ap.fluid_type == Constants.FluidWater
889
472
  plant_loop.setFluidType('Water')
890
473
  else
891
- plant_loop.setFluidType({ Constants.FluidPropyleneGlycol => 'PropyleneGlycol', Constants.FluidEthyleneGlycol => 'EthyleneGlycol' }[fluid_type])
892
- plant_loop.setGlycolConcentration((frac_glycol * 100).to_i)
474
+ plant_loop.setFluidType({ Constants.FluidPropyleneGlycol => 'PropyleneGlycol', Constants.FluidEthyleneGlycol => 'EthyleneGlycol' }[hp_ap.fluid_type])
475
+ plant_loop.setGlycolConcentration((hp_ap.frac_glycol * 100).to_i)
893
476
  end
894
477
  plant_loop.setMaximumLoopTemperature(48.88889)
895
- plant_loop.setMinimumLoopTemperature(UnitConversions.convert(hw_design, 'F', 'C'))
478
+ plant_loop.setMinimumLoopTemperature(UnitConversions.convert(hp_ap.design_hw, 'F', 'C'))
896
479
  plant_loop.setMinimumLoopFlowRate(0)
897
480
  plant_loop.setLoadDistributionScheme('SequentialLoad')
898
481
  plant_loop.addSupplyBranchForComponent(ground_heat_exch_vert)
899
482
  plant_loop.addDemandBranchForComponent(htg_coil)
900
483
  plant_loop.addDemandBranchForComponent(clg_coil)
484
+ plant_loop.setMaximumLoopFlowRate(UnitConversions.convert(hp_ap.GSHP_Loop_flow, 'gal/min', 'm^3/s'))
901
485
  hvac_map[heat_pump.id] << plant_loop
902
486
 
903
487
  sizing_plant = plant_loop.sizingPlant
904
488
  sizing_plant.setLoopType('Condenser')
905
- sizing_plant.setDesignLoopExitTemperature(UnitConversions.convert(chw_design, 'F', 'C'))
906
- sizing_plant.setLoopDesignTemperatureDifference(UnitConversions.convert(design_delta_t, 'R', 'K'))
489
+ sizing_plant.setDesignLoopExitTemperature(UnitConversions.convert(hp_ap.design_chw, 'F', 'C'))
490
+ sizing_plant.setLoopDesignTemperatureDifference(UnitConversions.convert(hp_ap.design_delta_t, 'R', 'K'))
907
491
 
908
492
  setpoint_mgr_follow_ground_temp = OpenStudio::Model::SetpointManagerFollowGroundTemperature.new(model)
909
493
  setpoint_mgr_follow_ground_temp.setName(obj_name + ' condenser loop temp')
910
494
  setpoint_mgr_follow_ground_temp.setControlVariable('Temperature')
911
495
  setpoint_mgr_follow_ground_temp.setMaximumSetpointTemperature(48.88889)
912
- setpoint_mgr_follow_ground_temp.setMinimumSetpointTemperature(UnitConversions.convert(hw_design, 'F', 'C'))
496
+ setpoint_mgr_follow_ground_temp.setMinimumSetpointTemperature(UnitConversions.convert(hp_ap.design_hw, 'F', 'C'))
913
497
  setpoint_mgr_follow_ground_temp.setReferenceGroundTemperatureObjectType('Site:GroundTemperature:Deep')
914
498
  setpoint_mgr_follow_ground_temp.addToNode(plant_loop.supplyOutletNode)
915
499
 
916
500
  # Pump
917
-
918
- # Pump power set in hvac_sizing.rb
919
501
  pump = OpenStudio::Model::PumpVariableSpeed.new(model)
920
502
  pump.setName(obj_name + ' pump')
921
503
  pump.setMotorEfficiency(0.85)
@@ -928,11 +510,18 @@ class HVAC
928
510
  pump.setMinimumFlowRate(0)
929
511
  pump.setPumpControlType('Intermittent')
930
512
  pump.addToNode(plant_loop.supplyInletNode)
513
+ if heat_pump.cooling_capacity > 1.0
514
+ pump_w = heat_pump.pump_watts_per_ton * UnitConversions.convert(heat_pump.cooling_capacity, 'Btu/hr', 'ton')
515
+ else
516
+ pump_w = heat_pump.pump_watts_per_ton * UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'ton')
517
+ end
518
+ pump_w = [pump_w, 1.0].max # prevent error if zero
519
+ pump.setRatedPowerConsumption(pump_w)
520
+ pump.setRatedFlowRate(calc_pump_rated_flow_rate(0.75, pump_w, pump.ratedPumpHead))
931
521
  hvac_map[heat_pump.id] << pump
932
522
  hvac_map[heat_pump.id] += disaggregate_fan_or_pump(model, pump, htg_coil, clg_coil, htg_supp_coil)
933
523
 
934
524
  # Pipes
935
-
936
525
  chiller_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
937
526
  plant_loop.addSupplyBranchForComponent(chiller_bypass_pipe)
938
527
  coil_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
@@ -945,14 +534,14 @@ class HVAC
945
534
  demand_outlet_pipe.addToNode(plant_loop.demandOutletNode)
946
535
 
947
536
  # Fan
948
-
949
- fan = create_supply_fan(model, obj_name, 1, heat_pump.fan_watts_per_cfm)
537
+ fan_cfm = [htg_cfm, clg_cfm].max
538
+ fan = create_supply_fan(model, obj_name, 1, heat_pump.fan_watts_per_cfm, fan_cfm)
950
539
  hvac_map[heat_pump.id] += disaggregate_fan_or_pump(model, fan, htg_coil, clg_coil, htg_supp_coil)
951
540
 
952
541
  # Unitary System
953
-
954
- air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, 40.0)
542
+ air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, htg_cfm, clg_cfm, 40.0)
955
543
  hvac_map[heat_pump.id] << air_loop_unitary
544
+ set_pump_power_ems_program(model, pump_w, pump, air_loop_unitary)
956
545
 
957
546
  if heat_pump.is_shared_system
958
547
  # Shared pump power per ANSI/RESNET/ICC 301-2019 Section 4.4.5.1 (pump runs 8760)
@@ -976,24 +565,11 @@ class HVAC
976
565
  end
977
566
 
978
567
  # Air Loop
979
-
980
- air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_frac, sequential_cool_load_frac)
568
+ air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_frac, sequential_cool_load_frac, fan_cfm)
981
569
  hvac_map[heat_pump.id] << air_loop
982
570
 
983
- # Store info for HVAC Sizing measure
984
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACSHR, heat_pump.cooling_shr.to_s)
985
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoGSHPCoil_BF_FT_SPEC, coil_bf_ft_spec.join(','))
986
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoGSHPCoilBF, coil_bf)
987
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACFracHeatLoadServed, heat_pump.fraction_heat_load_served)
988
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACFracCoolLoadServed, heat_pump.fraction_cool_load_served)
989
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoGSHPBoreSpacing, bore_spacing)
990
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoGSHPBoreHoles, bore_holes.to_s)
991
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoGSHPBoreDepth, bore_depth.to_s)
992
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoGSHPBoreConfig, bore_config.to_s)
993
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoGSHPUTubeSpacingType, u_tube_spacing_type)
994
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACCoolType, Constants.ObjectNameGroundSourceHeatPump)
995
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACHeatType, Constants.ObjectNameGroundSourceHeatPump)
996
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACPumpPower, heat_pump.pump_watts_per_ton)
571
+ # HVAC Installation Quality
572
+ apply_installation_quality(model, heat_pump, heat_pump, air_loop_unitary, htg_coil, clg_coil, control_zone)
997
573
  end
998
574
 
999
575
  def self.apply_water_loop_to_air_heat_pump(model, runner, heat_pump,
@@ -1009,10 +585,11 @@ class HVAC
1009
585
  obj_name = Constants.ObjectNameWaterLoopHeatPump
1010
586
  sequential_heat_load_frac = calc_sequential_load_fraction(heat_pump.fraction_heat_load_served, remaining_heat_load_frac)
1011
587
  sequential_cool_load_frac = 0.0
1012
- hp_min_temp, supp_max_temp = get_heat_pump_temp_assumptions(heat_pump)
1013
588
 
1014
- # Cooling Coil
589
+ hp_ap = heat_pump.additional_properties
590
+ htg_cfm = heat_pump.heating_airflow_cfm
1015
591
 
592
+ # Cooling Coil (none)
1016
593
  clg_coil = nil
1017
594
 
1018
595
  # Heating Coil (model w/ constant efficiency)
@@ -1022,35 +599,27 @@ class HVAC
1022
599
  htg_coil.setName(obj_name + ' htg coil')
1023
600
  htg_coil.setRatedCOP(heat_pump.heating_efficiency_cop)
1024
601
  htg_coil.setDefrostTimePeriodFraction(0.00001) # Disable defrost; avoid E+ warning w/ value of zero
1025
- htg_coil.setMinimumOutdoorDryBulbTemperatureforCompressorOperation(UnitConversions.convert(hp_min_temp, 'F', 'C'))
602
+ htg_coil.setMinimumOutdoorDryBulbTemperatureforCompressorOperation(UnitConversions.convert(hp_ap.hp_min_temp, 'F', 'C'))
603
+ htg_coil.setRatedTotalHeatingCapacity(UnitConversions.convert(heat_pump.heating_capacity, 'Btu/hr', 'W'))
604
+ htg_coil.setRatedAirFlowRate(htg_cfm)
1026
605
  hvac_map[heat_pump.id] << htg_coil
1027
606
 
1028
607
  # Supplemental Heating Coil
1029
-
1030
608
  htg_supp_coil = create_supp_heating_coil(model, obj_name, heat_pump)
1031
609
  hvac_map[heat_pump.id] << htg_supp_coil
1032
610
 
1033
611
  # Fan
1034
-
1035
- fan_power_installed = 0.5 # FIXME
1036
- fan = create_supply_fan(model, obj_name, 1, fan_power_installed)
612
+ fan_power_installed = 0.0 # Use provided net COP
613
+ fan = create_supply_fan(model, obj_name, 1, fan_power_installed, htg_cfm)
1037
614
  hvac_map[heat_pump.id] += disaggregate_fan_or_pump(model, fan, htg_coil, clg_coil, htg_supp_coil)
1038
615
 
1039
616
  # Unitary System
1040
-
1041
- air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, supp_max_temp)
617
+ air_loop_unitary = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, htg_cfm, nil, hp_ap.supp_max_temp)
1042
618
  hvac_map[heat_pump.id] << air_loop_unitary
1043
619
 
1044
620
  # Air Loop
1045
-
1046
- air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_frac, sequential_cool_load_frac)
621
+ air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_frac, sequential_cool_load_frac, htg_cfm)
1047
622
  hvac_map[heat_pump.id] << air_loop
1048
-
1049
- # Store info for HVAC Sizing measure
1050
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACFracHeatLoadServed, heat_pump.fraction_heat_load_served)
1051
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACFracCoolLoadServed, heat_pump.fraction_cool_load_served)
1052
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACCoolType, Constants.ObjectNameWaterLoopHeatPump)
1053
- air_loop_unitary.additionalProperties.setFeature(Constants.SizingInfoHVACHeatType, Constants.ObjectNameWaterLoopHeatPump)
1054
623
  end
1055
624
 
1056
625
  def self.apply_boiler(model, runner, heating_system,
@@ -1076,7 +645,6 @@ class HVAC
1076
645
  end
1077
646
 
1078
647
  # Plant Loop
1079
-
1080
648
  plant_loop = OpenStudio::Model::PlantLoop.new(model)
1081
649
  plant_loop.setName(obj_name + ' hydronic heat loop')
1082
650
  plant_loop.setFluidType('Water')
@@ -1092,8 +660,8 @@ class HVAC
1092
660
  loop_sizing.setLoopDesignTemperatureDifference(UnitConversions.convert(20.0, 'R', 'K'))
1093
661
 
1094
662
  # Pump
1095
-
1096
663
  pump_w = heating_system.electric_auxiliary_energy / 2.08
664
+ pump_w = [pump_w, 1.0].max # prevent error if zero
1097
665
  pump = OpenStudio::Model::PumpVariableSpeed.new(model)
1098
666
  pump.setName(obj_name + ' hydronic pump')
1099
667
  pump.setRatedPowerConsumption(pump_w)
@@ -1110,13 +678,9 @@ class HVAC
1110
678
  hvac_map[heating_system.id] << pump
1111
679
 
1112
680
  # Boiler
1113
-
1114
681
  boiler = OpenStudio::Model::BoilerHotWater.new(model)
1115
682
  boiler.setName(obj_name)
1116
- boiler.setFuelType(EPlus.input_fuel_map(heating_system.heating_system_fuel))
1117
- if not heating_system.heating_capacity.nil?
1118
- boiler.setNominalCapacity(UnitConversions.convert([heating_system.heating_capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
1119
- end
683
+ boiler.setFuelType(EPlus.fuel_type(heating_system.heating_system_fuel))
1120
684
  if is_condensing
1121
685
  # Convert Rated Efficiency at 80F and 1.0PLR where the performance curves are derived from to Design condition as input
1122
686
  boiler_RatedHWRT = UnitConversions.convert(80.0 - 32.0, 'R', 'K')
@@ -1142,6 +706,7 @@ class HVAC
1142
706
  boiler.setOptimumPartLoadRatio(1.0)
1143
707
  boiler.setWaterOutletUpperTemperatureLimit(99.9)
1144
708
  boiler.setParasiticElectricLoad(0)
709
+ boiler.setNominalCapacity(UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W'))
1145
710
  plant_loop.addSupplyBranchForComponent(boiler)
1146
711
  hvac_map[heating_system.id] << boiler
1147
712
  set_pump_power_ems_program(model, pump_w, pump, boiler)
@@ -1177,16 +742,21 @@ class HVAC
1177
742
  pipe_demand_outlet = OpenStudio::Model::PipeAdiabatic.new(model)
1178
743
  pipe_demand_outlet.addToNode(plant_loop.demandOutletNode)
1179
744
 
1180
- if heating_system.distribution_system.hydronic_and_air_type.to_s == HPXML::HydronicAndAirTypeFanCoil
745
+ bb_ua = UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W') / UnitConversions.convert(UnitConversions.convert(loop_sizing.designLoopExitTemperature, 'C', 'F') - 10.0 - 95.0, 'R', 'K') * 3.0 # W/K
746
+ max_water_flow = UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W') / UnitConversions.convert(20.0, 'R', 'K') / 4.186 / 998.2 / 1000.0 * 2.0 # m^3/s
747
+ fan_cfm = 400.0 * UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'ton') # CFM; assumes 400 cfm/ton
748
+
749
+ if heating_system.distribution_system.air_type.to_s == HPXML::AirTypeFanCoil
1181
750
  # Fan
1182
- fan = create_supply_fan(model, obj_name, 1, 0.0) # fan energy included in above pump via Electrix Auxiliar Energy (EAE)
751
+ fan = create_supply_fan(model, obj_name, 1, 0.0, fan_cfm) # fan energy included in above pump via Electric Auxiliary Energy (EAE)
1183
752
 
1184
753
  # Heating Coil
1185
754
  htg_coil = OpenStudio::Model::CoilHeatingWater.new(model, model.alwaysOnDiscreteSchedule)
755
+ htg_coil.setRatedCapacity(UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W'))
756
+ htg_coil.setUFactorTimesAreaValue(bb_ua)
757
+ htg_coil.setMaximumWaterFlowRate(max_water_flow)
758
+ htg_coil.setPerformanceInputMethod('NominalCapacity')
1186
759
  htg_coil.setName(obj_name + ' htg coil')
1187
- if not heating_system.heating_capacity.nil?
1188
- htg_coil.setRatedCapacity(UnitConversions.convert([heating_system.heating_capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
1189
- end
1190
760
  plant_loop.addDemandBranchForComponent(htg_coil)
1191
761
 
1192
762
  # Cooling Coil (always off)
@@ -1210,6 +780,8 @@ class HVAC
1210
780
  zone_hvac.setMaximumColdWaterFlowRate(0.0)
1211
781
  zone_hvac.setCoolingConvergenceTolerance(0.001)
1212
782
  zone_hvac.setMaximumOutdoorAirFlowRate(0.0)
783
+ zone_hvac.setMaximumSupplyAirFlowRate(UnitConversions.convert(fan_cfm, 'cfm', 'm^3/s'))
784
+ zone_hvac.setMaximumHotWaterFlowRate(max_water_flow)
1213
785
  zone_hvac.addToThermalZone(control_zone)
1214
786
  hvac_map[heating_system.id] << zone_hvac
1215
787
  hvac_map[heating_system.id] += disaggregate_fan_or_pump(model, pump, zone_hvac, nil, nil)
@@ -1217,10 +789,11 @@ class HVAC
1217
789
  # Heating Coil
1218
790
  htg_coil = OpenStudio::Model::CoilHeatingWaterBaseboard.new(model)
1219
791
  htg_coil.setName(obj_name + ' htg coil')
1220
- if not heating_system.heating_capacity.nil?
1221
- htg_coil.setHeatingDesignCapacity(UnitConversions.convert([heating_system.heating_capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
1222
- end
1223
792
  htg_coil.setConvergenceTolerance(0.001)
793
+ htg_coil.setHeatingDesignCapacity(UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W'))
794
+ htg_coil.setUFactorTimesAreaValue(bb_ua)
795
+ htg_coil.setMaximumWaterFlowRate(max_water_flow)
796
+ htg_coil.setHeatingDesignCapacityMethod('HeatingDesignCapacity')
1224
797
  plant_loop.addDemandBranchForComponent(htg_coil)
1225
798
  hvac_map[heating_system.id] << htg_coil
1226
799
 
@@ -1234,10 +807,6 @@ class HVAC
1234
807
 
1235
808
  control_zone.setSequentialHeatingFractionSchedule(zone_hvac, get_sequential_load_schedule(model, sequential_heat_load_frac))
1236
809
  control_zone.setSequentialCoolingFractionSchedule(zone_hvac, get_sequential_load_schedule(model, 0))
1237
-
1238
- # Store info for HVAC Sizing measure
1239
- zone_hvac.additionalProperties.setFeature(Constants.SizingInfoHVACFracHeatLoadServed, heating_system.fraction_heat_load_served)
1240
- zone_hvac.additionalProperties.setFeature(Constants.SizingInfoHVACHeatType, Constants.ObjectNameBoiler)
1241
810
  end
1242
811
 
1243
812
  def self.apply_electric_baseboard(model, runner, heating_system,
@@ -1249,22 +818,15 @@ class HVAC
1249
818
  sequential_heat_load_frac = calc_sequential_load_fraction(heating_system.fraction_heat_load_served, remaining_heat_load_frac)
1250
819
 
1251
820
  # Baseboard
1252
-
1253
821
  zone_hvac = OpenStudio::Model::ZoneHVACBaseboardConvectiveElectric.new(model)
1254
822
  zone_hvac.setName(obj_name)
1255
- if not heating_system.heating_capacity.nil?
1256
- zone_hvac.setNominalCapacity(UnitConversions.convert([heating_system.heating_capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
1257
- end
1258
823
  zone_hvac.setEfficiency(heating_system.heating_efficiency_percent)
824
+ zone_hvac.setNominalCapacity(UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W'))
1259
825
  zone_hvac.addToThermalZone(control_zone)
1260
826
  hvac_map[heating_system.id] << zone_hvac
1261
827
 
1262
828
  control_zone.setSequentialHeatingFractionSchedule(zone_hvac, get_sequential_load_schedule(model, sequential_heat_load_frac))
1263
829
  control_zone.setSequentialCoolingFractionSchedule(zone_hvac, get_sequential_load_schedule(model, 0))
1264
-
1265
- # Store info for HVAC Sizing measure
1266
- zone_hvac.additionalProperties.setFeature(Constants.SizingInfoHVACFracHeatLoadServed, heating_system.fraction_heat_load_served)
1267
- zone_hvac.additionalProperties.setFeature(Constants.SizingInfoHVACHeatType, Constants.ObjectNameElectricBaseboard)
1268
830
  end
1269
831
 
1270
832
  def self.apply_unit_heater(model, runner, heating_system,
@@ -1274,15 +836,10 @@ class HVAC
1274
836
  hvac_map[heating_system.id] = []
1275
837
  obj_name = Constants.ObjectNameUnitHeater
1276
838
  sequential_heat_load_frac = calc_sequential_load_fraction(heating_system.fraction_heat_load_served, remaining_heat_load_frac)
1277
- fan_power_installed = 0.5 # W/cfm # For fuel equipment, will be overridden by EAE later
1278
- airflow_rate = 125.0 # cfm/ton; doesn't affect energy consumption
1279
839
 
1280
- if (fan_power_installed > 0) && (airflow_rate == 0)
1281
- fail 'If Fan Power > 0, then Airflow Rate cannot be zero.'
1282
- end
840
+ htg_ap = heating_system.additional_properties
1283
841
 
1284
842
  # Heating Coil
1285
-
1286
843
  efficiency = heating_system.heating_efficiency_afue
1287
844
  efficiency = heating_system.heating_efficiency_percent if efficiency.nil?
1288
845
  if heating_system.heating_system_fuel == HPXML::FuelTypeElectricity
@@ -1293,40 +850,32 @@ class HVAC
1293
850
  htg_coil.setGasBurnerEfficiency(efficiency)
1294
851
  htg_coil.setParasiticElectricLoad(0.0)
1295
852
  htg_coil.setParasiticGasLoad(0)
1296
- htg_coil.setFuelType(EPlus.input_fuel_map(heating_system.heating_system_fuel))
853
+ htg_coil.setFuelType(EPlus.fuel_type(heating_system.heating_system_fuel))
1297
854
  end
855
+ htg_coil.setNominalCapacity(UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W'))
1298
856
  htg_coil.setName(obj_name + ' htg coil')
1299
- if not heating_system.heating_capacity.nil?
1300
- htg_coil.setNominalCapacity(UnitConversions.convert([heating_system.heating_capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
1301
- end
1302
857
  hvac_map[heating_system.id] << htg_coil
1303
858
 
1304
859
  # Fan
1305
-
1306
- fan = create_supply_fan(model, obj_name, 1, fan_power_installed)
860
+ htg_cfm = heating_system.heating_airflow_cfm
861
+ fan_watts_per_cfm = heating_system.fan_watts / htg_cfm
862
+ fan = create_supply_fan(model, obj_name, 1, fan_watts_per_cfm, htg_cfm)
1307
863
  hvac_map[heating_system.id] += disaggregate_fan_or_pump(model, fan, htg_coil, nil, nil)
1308
864
 
1309
865
  # Unitary System
1310
-
1311
- unitary_system = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, nil, nil)
866
+ unitary_system = create_air_loop_unitary_system(model, obj_name, fan, htg_coil, nil, nil, htg_cfm, nil)
1312
867
  unitary_system.setControllingZoneorThermostatLocation(control_zone)
1313
868
  unitary_system.addToThermalZone(control_zone)
1314
869
  hvac_map[heating_system.id] << unitary_system
1315
870
 
1316
871
  control_zone.setSequentialHeatingFractionSchedule(unitary_system, get_sequential_load_schedule(model, sequential_heat_load_frac))
1317
872
  control_zone.setSequentialCoolingFractionSchedule(unitary_system, get_sequential_load_schedule(model, 0))
1318
-
1319
- # Store info for HVAC Sizing measure
1320
- unitary_system.additionalProperties.setFeature(Constants.SizingInfoHVACRatedCFMperTonHeating, airflow_rate.to_s)
1321
- unitary_system.additionalProperties.setFeature(Constants.SizingInfoHVACFracHeatLoadServed, heating_system.fraction_heat_load_served)
1322
- unitary_system.additionalProperties.setFeature(Constants.SizingInfoHVACHeatType, Constants.ObjectNameUnitHeater)
1323
873
  end
1324
874
 
1325
875
  def self.apply_ideal_air_loads(model, runner, obj_name, sequential_cool_load_frac,
1326
876
  sequential_heat_load_frac, control_zone)
1327
877
 
1328
878
  # Ideal Air System
1329
-
1330
879
  ideal_air = OpenStudio::Model::ZoneHVACIdealLoadsAirSystem.new(model)
1331
880
  ideal_air.setName(obj_name)
1332
881
  ideal_air.setMaximumHeatingSupplyAirTemperature(50)
@@ -1351,62 +900,70 @@ class HVAC
1351
900
 
1352
901
  control_zone.setSequentialCoolingFractionSchedule(ideal_air, get_sequential_load_schedule(model, sequential_cool_load_frac))
1353
902
  control_zone.setSequentialHeatingFractionSchedule(ideal_air, get_sequential_load_schedule(model, sequential_heat_load_frac))
1354
-
1355
- # Store info for HVAC Sizing measure
1356
- ideal_air.additionalProperties.setFeature(Constants.SizingInfoHVACCoolType, Constants.ObjectNameIdealAirSystem)
1357
- ideal_air.additionalProperties.setFeature(Constants.SizingInfoHVACHeatType, Constants.ObjectNameIdealAirSystem)
1358
903
  end
1359
904
 
1360
- def self.apply_dehumidifier(model, runner, dehumidifier, living_space, hvac_map)
1361
- hvac_map[dehumidifier.id] = []
1362
-
1363
- water_removal_rate = dehumidifier.capacity
1364
- energy_factor = dehumidifier.energy_factor
1365
-
1366
- control_zone = living_space.thermalZone.get
1367
- obj_name = Constants.ObjectNameDehumidifier
905
+ def self.apply_dehumidifiers(model, runner, dehumidifiers, living_space, hvac_map)
906
+ dehumidifier_id = dehumidifiers[0].id # Syncs with SimulationOutputReport, which only looks at first dehumidifier ID
907
+ hvac_map[dehumidifier_id] = []
1368
908
 
1369
- avg_rh_setpoint = dehumidifier.rh_setpoint * 100.0 # (EnergyPlus uses 60 for 60% RH)
1370
- relative_humidity_setpoint_sch = OpenStudio::Model::ScheduleConstant.new(model)
1371
- relative_humidity_setpoint_sch.setName(Constants.ObjectNameRelativeHumiditySetpoint)
1372
- relative_humidity_setpoint_sch.setValue(avg_rh_setpoint)
909
+ if dehumidifiers.map { |d| d.rh_setpoint }.uniq.size > 1
910
+ fail 'All dehumidifiers must have the same setpoint but multiple setpoints were specified.'
911
+ end
1373
912
 
1374
913
  # Dehumidifier coefficients
1375
914
  # Generic model coefficients from Winkler, Christensen, and Tomerlin (2011)
1376
915
  w_coeff = [-1.162525707, 0.02271469, -0.000113208, 0.021110538, -0.0000693034, 0.000378843]
1377
916
  ef_coeff = [-1.902154518, 0.063466565, -0.000622839, 0.039540407, -0.000125637, -0.000176722]
1378
917
  pl_coeff = [0.90, 0.10, 0.0]
1379
- water_removal_curve = create_curve_biquadratic(model, w_coeff, 'DXDH-WaterRemove-Cap-fT', -100, 100, -100, 100)
1380
- energy_factor_curve = create_curve_biquadratic(model, ef_coeff, 'DXDH-EnergyFactor-fT', -100, 100, -100, 100)
1381
- part_load_frac_curve = create_curve_quadratic(model, pl_coeff, 'DXDH-PLF-fPLR', 0, 1, 0.7, 1)
1382
- if energy_factor.nil?
918
+
919
+ dehumidifiers.each do |d|
920
+ next unless d.energy_factor.nil?
921
+
1383
922
  # shift inputs tested under IEF test conditions to those under EF test conditions with performance curves
1384
- energy_factor, water_removal_rate = apply_dehumidifier_ief_to_ef_inputs(w_coeff, ef_coeff, dehumidifier.integrated_energy_factor, water_removal_rate)
923
+ d.energy_factor, d.capacity = apply_dehumidifier_ief_to_ef_inputs(d.type, w_coeff, ef_coeff, d.integrated_energy_factor, d.capacity)
1385
924
  end
1386
925
 
926
+ total_capacity = dehumidifiers.map { |d| d.capacity }.sum
927
+ avg_energy_factor = dehumidifiers.map { |d| d.energy_factor * d.capacity }.sum / total_capacity
928
+ total_fraction_served = dehumidifiers.map { |d| d.fraction_served }.sum
929
+
930
+ control_zone = living_space.thermalZone.get
931
+ obj_name = Constants.ObjectNameDehumidifier
932
+
933
+ rh_setpoint = dehumidifiers[0].rh_setpoint * 100.0 # (EnergyPlus uses 60 for 60% RH)
934
+ relative_humidity_setpoint_sch = OpenStudio::Model::ScheduleConstant.new(model)
935
+ relative_humidity_setpoint_sch.setName(Constants.ObjectNameRelativeHumiditySetpoint)
936
+ relative_humidity_setpoint_sch.setValue(rh_setpoint)
937
+
938
+ capacity_curve = create_curve_biquadratic(model, w_coeff, 'DXDH-CAP-fT', -100, 100, -100, 100)
939
+ energy_factor_curve = create_curve_biquadratic(model, ef_coeff, 'DXDH-EF-fT', -100, 100, -100, 100)
940
+ part_load_frac_curve = create_curve_quadratic(model, pl_coeff, 'DXDH-PLF-fPLR', 0, 1, 0.7, 1)
941
+
1387
942
  # Calculate air flow rate by assuming 2.75 cfm/pint/day (based on experimental test data)
1388
- air_flow_rate = 2.75 * water_removal_rate
943
+ air_flow_rate = 2.75 * total_capacity
1389
944
 
945
+ # Humidity Setpoint
1390
946
  humidistat = OpenStudio::Model::ZoneControlHumidistat.new(model)
1391
947
  humidistat.setName(obj_name + ' humidistat')
1392
948
  humidistat.setHumidifyingRelativeHumiditySetpointSchedule(relative_humidity_setpoint_sch)
1393
949
  humidistat.setDehumidifyingRelativeHumiditySetpointSchedule(relative_humidity_setpoint_sch)
1394
950
  control_zone.setZoneControlHumidistat(humidistat)
1395
951
 
1396
- zone_hvac = OpenStudio::Model::ZoneHVACDehumidifierDX.new(model, water_removal_curve, energy_factor_curve, part_load_frac_curve)
952
+ # Dehumidifier
953
+ zone_hvac = OpenStudio::Model::ZoneHVACDehumidifierDX.new(model, capacity_curve, energy_factor_curve, part_load_frac_curve)
1397
954
  zone_hvac.setName(obj_name)
1398
955
  zone_hvac.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
1399
- zone_hvac.setRatedWaterRemoval(UnitConversions.convert(water_removal_rate, 'pint', 'L'))
1400
- zone_hvac.setRatedEnergyFactor(energy_factor / dehumidifier.fraction_served)
956
+ zone_hvac.setRatedWaterRemoval(UnitConversions.convert(total_capacity, 'pint', 'L'))
957
+ zone_hvac.setRatedEnergyFactor(avg_energy_factor / total_fraction_served)
1401
958
  zone_hvac.setRatedAirFlowRate(UnitConversions.convert(air_flow_rate, 'cfm', 'm^3/s'))
1402
959
  zone_hvac.setMinimumDryBulbTemperatureforDehumidifierOperation(10)
1403
960
  zone_hvac.setMaximumDryBulbTemperatureforDehumidifierOperation(40)
1404
961
 
1405
962
  zone_hvac.addToThermalZone(control_zone)
1406
963
 
1407
- hvac_map[dehumidifier.id] << zone_hvac
1408
- if dehumidifier.fraction_served < 1.0
1409
- adjust_dehumidifier_load_EMS(dehumidifier.fraction_served, zone_hvac, model, living_space)
964
+ hvac_map[dehumidifier_id] << zone_hvac
965
+ if total_fraction_served < 1.0
966
+ adjust_dehumidifier_load_EMS(total_fraction_served, zone_hvac, model, living_space)
1410
967
  end
1411
968
  end
1412
969
 
@@ -1445,56 +1002,77 @@ class HVAC
1445
1002
  equip.setSchedule(ceiling_fan_sch)
1446
1003
  end
1447
1004
 
1448
- def self.apply_setpoints(model, runner, weather, hvac_control, living_zone)
1005
+ def self.apply_setpoints(model, runner, weather, hvac_control, living_zone, has_ceiling_fan)
1449
1006
  # Assume heating/cooling seasons are year-round
1450
1007
  htg_start_month = 1
1451
1008
  htg_end_month = 12
1452
1009
  clg_start_month = 1
1453
1010
  clg_end_month = 12
1454
1011
 
1455
- # Base heating setpoint
1456
- htg_setpoint = hvac_control.heating_setpoint_temp
1457
- htg_weekday_setpoints = [[htg_setpoint] * 24] * 12
1458
-
1459
- # Apply heating setback?
1460
- htg_setback = hvac_control.heating_setback_temp
1461
- if not htg_setback.nil?
1462
- htg_setback_hrs_per_week = hvac_control.heating_setback_hours_per_week
1463
- htg_setback_start_hr = hvac_control.heating_setback_start_hour
1464
- for m in 1..12
1465
- for hr in htg_setback_start_hr..htg_setback_start_hr + Integer(htg_setback_hrs_per_week / 7.0) - 1
1466
- htg_weekday_setpoints[m - 1][hr % 24] = htg_setback
1012
+ if hvac_control.weekday_heating_setpoints.nil? || hvac_control.weekend_heating_setpoints.nil?
1013
+ # Base heating setpoint
1014
+ htg_setpoint = hvac_control.heating_setpoint_temp
1015
+ htg_weekday_setpoints = [[htg_setpoint] * 24] * 12
1016
+
1017
+ # Apply heating setback?
1018
+ htg_setback = hvac_control.heating_setback_temp
1019
+ if not htg_setback.nil?
1020
+ htg_setback_hrs_per_week = hvac_control.heating_setback_hours_per_week
1021
+ htg_setback_start_hr = hvac_control.heating_setback_start_hour
1022
+ for m in 1..12
1023
+ for hr in htg_setback_start_hr..htg_setback_start_hr + Integer(htg_setback_hrs_per_week / 7.0) - 1
1024
+ htg_weekday_setpoints[m - 1][hr % 24] = htg_setback
1025
+ end
1467
1026
  end
1468
1027
  end
1469
- end
1470
- htg_weekend_setpoints = htg_weekday_setpoints
1471
-
1472
- # Base cooling setpoint
1473
- clg_setpoint = hvac_control.cooling_setpoint_temp
1474
- clg_weekday_setpoints = [[clg_setpoint] * 24] * 12
1475
-
1476
- # Apply cooling setup?
1477
- clg_setup = hvac_control.cooling_setup_temp
1478
- if not clg_setup.nil?
1479
- clg_setup_hrs_per_week = hvac_control.cooling_setup_hours_per_week
1480
- clg_setup_start_hr = hvac_control.cooling_setup_start_hour
1481
- for m in 1..12
1482
- for hr in clg_setup_start_hr..clg_setup_start_hr + Integer(clg_setup_hrs_per_week / 7.0) - 1
1483
- clg_weekday_setpoints[m - 1][hr % 24] = clg_setup
1028
+ htg_weekend_setpoints = htg_weekday_setpoints.dup
1029
+ else
1030
+ # 24-hr weekday/weekend heating setpoint schedules
1031
+ htg_weekday_setpoints = hvac_control.weekday_heating_setpoints.split(',').map { |i| Float(i) }
1032
+ htg_weekday_setpoints = [htg_weekday_setpoints] * 12
1033
+
1034
+ htg_weekend_setpoints = hvac_control.weekend_heating_setpoints.split(',').map { |i| Float(i) }
1035
+ htg_weekend_setpoints = [htg_weekend_setpoints] * 12
1036
+ end
1037
+
1038
+ if hvac_control.weekday_cooling_setpoints.nil? || hvac_control.weekend_cooling_setpoints.nil?
1039
+ # Base cooling setpoint
1040
+ clg_setpoint = hvac_control.cooling_setpoint_temp
1041
+ clg_weekday_setpoints = [[clg_setpoint] * 24] * 12
1042
+
1043
+ # Apply cooling setup?
1044
+ clg_setup = hvac_control.cooling_setup_temp
1045
+ if not clg_setup.nil?
1046
+ clg_setup_hrs_per_week = hvac_control.cooling_setup_hours_per_week
1047
+ clg_setup_start_hr = hvac_control.cooling_setup_start_hour
1048
+ for m in 1..12
1049
+ for hr in clg_setup_start_hr..clg_setup_start_hr + Integer(clg_setup_hrs_per_week / 7.0) - 1
1050
+ clg_weekday_setpoints[m - 1][hr % 24] = clg_setup
1051
+ end
1484
1052
  end
1485
1053
  end
1054
+ clg_weekend_setpoints = clg_weekday_setpoints.dup
1055
+ else
1056
+ # 24-hr weekday/weekend cooling setpoint schedules
1057
+ clg_weekday_setpoints = hvac_control.weekday_cooling_setpoints.split(',').map { |i| Float(i) }
1058
+ clg_weekday_setpoints = [clg_weekday_setpoints] * 12
1059
+
1060
+ clg_weekend_setpoints = hvac_control.weekend_cooling_setpoints.split(',').map { |i| Float(i) }
1061
+ clg_weekend_setpoints = [clg_weekend_setpoints] * 12
1486
1062
  end
1487
1063
 
1488
1064
  # Apply cooling setpoint offset due to ceiling fan?
1489
- clg_ceiling_fan_offset = hvac_control.ceiling_fan_cooling_setpoint_temp_offset
1490
- if not clg_ceiling_fan_offset.nil?
1491
- HVAC.get_default_ceiling_fan_months(weather).each_with_index do |operation, m|
1492
- next unless operation == 1
1493
-
1494
- clg_weekday_setpoints[m] = [clg_weekday_setpoints[m], Array.new(24, clg_ceiling_fan_offset)].transpose.map { |i| i.reduce(:+) }
1065
+ if has_ceiling_fan
1066
+ clg_ceiling_fan_offset = hvac_control.ceiling_fan_cooling_setpoint_temp_offset
1067
+ if not clg_ceiling_fan_offset.nil?
1068
+ get_default_ceiling_fan_months(weather).each_with_index do |operation, m|
1069
+ next unless operation == 1
1070
+
1071
+ clg_weekday_setpoints[m] = [clg_weekday_setpoints[m], Array.new(24, clg_ceiling_fan_offset)].transpose.map { |i| i.reduce(:+) }
1072
+ clg_weekend_setpoints[m] = [clg_weekend_setpoints[m], Array.new(24, clg_ceiling_fan_offset)].transpose.map { |i| i.reduce(:+) }
1073
+ end
1495
1074
  end
1496
1075
  end
1497
- clg_weekend_setpoints = clg_weekday_setpoints
1498
1076
 
1499
1077
  # Create heating season schedule
1500
1078
  if htg_start_month <= htg_end_month
@@ -1553,48 +1131,6 @@ class HVAC
1553
1131
  living_zone.setThermostatSetpointDualSetpoint(thermostat_setpoint)
1554
1132
  end
1555
1133
 
1556
- def self.apply_eae_to_heating_fan(runner, hvac_objects, heating_system)
1557
- # Applies Electric Auxiliary Energy (EAE) for fuel heating equipment to fan/pump power.
1558
-
1559
- eae = heating_system.electric_auxiliary_energy
1560
-
1561
- unitary_systems = []
1562
- hvac_objects.each do |hvac_object|
1563
- if hvac_object.is_a? OpenStudio::Model::AirLoopHVAC # Furnace
1564
- unitary_systems << get_unitary_system_from_air_loop_hvac(hvac_object)
1565
- elsif hvac_object.is_a? OpenStudio::Model::AirLoopHVACUnitarySystem # WallFurnace/FloorFurnace/Stove
1566
- unitary_systems << hvac_object
1567
- end
1568
- end
1569
-
1570
- unitary_systems.each do |unitary_system|
1571
- if eae.nil?
1572
- htg_coil = unitary_system.heatingCoil.get.to_CoilHeatingGas.get
1573
- htg_capacity = UnitConversions.convert(htg_coil.nominalCapacity.get, 'W', 'kBtu/hr')
1574
- eae = get_electric_auxiliary_energy(heating_system, htg_capacity)
1575
- end
1576
- elec_power = eae / 2.08 # W
1577
-
1578
- htg_coil = unitary_system.heatingCoil.get.to_CoilHeatingGas.get
1579
- htg_coil.setParasiticElectricLoad(0.0)
1580
-
1581
- htg_cfm = UnitConversions.convert(unitary_system.supplyAirFlowRateDuringHeatingOperation.get, 'm^3/s', 'cfm')
1582
-
1583
- fan = unitary_system.supplyFan.get.to_FanOnOff.get
1584
- if elec_power > 0
1585
- fan_eff = 0.75 # Overall Efficiency of the Fan, Motor and Drive
1586
- fan_w_cfm = elec_power / htg_cfm # W/cfm
1587
- fan.setFanEfficiency(fan_eff)
1588
- fan.setPressureRise(calc_fan_pressure_rise(fan_eff, fan_w_cfm))
1589
- else
1590
- fan.setFanEfficiency(1)
1591
- fan.setPressureRise(0)
1592
- end
1593
- fan.setMotorEfficiency(1.0)
1594
- fan.setMotorInAirstreamFraction(1.0)
1595
- end
1596
- end
1597
-
1598
1134
  def self.get_default_heating_setpoint(control_type)
1599
1135
  # Per ANSI/RESNET/ICC 301
1600
1136
  htg_sp = 68 # F
@@ -1627,22 +1163,242 @@ class HVAC
1627
1163
  return clg_sp, clg_setup_sp, clg_setup_hrs_per_week, clg_setup_start_hr
1628
1164
  end
1629
1165
 
1630
- def self.get_default_compressor_type(seer)
1631
- if seer <= 15
1632
- return HPXML::HVACCompressorTypeSingleStage
1633
- elsif seer <= 21
1634
- return HPXML::HVACCompressorTypeTwoStage
1635
- elsif seer > 21
1636
- return HPXML::HVACCompressorTypeVariableSpeed
1166
+ def self.set_cool_curves_ashp(heat_pump)
1167
+ hp_ap = heat_pump.additional_properties
1168
+ if hp_ap.num_speeds == 1
1169
+ # From "Improved Modeling of Residential Air Conditioners and Heat Pumps for Energy Calculations", Cutler at al
1170
+ # https://www.nrel.gov/docs/fy13osti/56354.pdf
1171
+ hp_ap.cool_rated_airflow_rate = 394.2 # cfm/ton of rated capacity
1172
+ hp_ap.cool_capacity_ratios = [1.0]
1173
+ hp_ap.cool_fan_speed_ratios = [1.0]
1174
+ hp_ap.cool_rated_shrs_net = [heat_pump.cooling_shr]
1175
+ hp_ap.cool_cap_ft_spec = [[3.68637657, -0.098352478, 0.000956357, 0.005838141, -0.0000127, -0.000131702]]
1176
+ hp_ap.cool_eir_ft_spec = [[-3.437356399, 0.136656369, -0.001049231, -0.0079378, 0.000185435, -0.0001441]]
1177
+ # Single stage systems have PSC or constant torque ECM blowers, so the airflow rate is affected by the static pressure losses.
1178
+ hp_ap.cool_cap_fflow_spec = [[0.718664047, 0.41797409, -0.136638137]]
1179
+ hp_ap.cool_eir_fflow_spec = [[1.143487507, -0.13943972, -0.004047787]]
1180
+ hp_ap.cool_eers = [calc_eer_cooling_1speed(heat_pump.cooling_efficiency_seer, hp_ap.cool_c_d, hp_ap.fan_power_rated, hp_ap.cool_eir_ft_spec)]
1181
+ elsif hp_ap.num_speeds == 2
1182
+ # From "Improved Modeling of Residential Air Conditioners and Heat Pumps for Energy Calculations", Cutler at al
1183
+ # https://www.nrel.gov/docs/fy13osti/56354.pdf
1184
+ hp_ap.cool_rated_airflow_rate = 344.1 # cfm/ton
1185
+ hp_ap.cool_capacity_ratios = [0.72, 1.0]
1186
+ hp_ap.cool_fan_speed_ratios = [0.86, 1.0]
1187
+ hp_ap.cool_rated_shrs_net = [heat_pump.cooling_shr - 0.014, heat_pump.cooling_shr] # TODO: is the following assumption correct (revisit Dylan's data?)? OR should value from HPXML be used for both stages?
1188
+ hp_ap.cool_cap_ft_spec = [[3.998418659, -0.108728222, 0.001056818, 0.007512314, -0.0000139, -0.000164716],
1189
+ [3.466810106, -0.091476056, 0.000901205, 0.004163355, -0.00000919, -0.000110829]]
1190
+ hp_ap.cool_eir_ft_spec = [[-4.282911381, 0.181023691, -0.001357391, -0.026310378, 0.000333282, -0.000197405],
1191
+ [-3.557757517, 0.112737397, -0.000731381, 0.013184877, 0.000132645, -0.000338716]]
1192
+ # Most two stage systems have PSC or constant torque ECM blowers, so the airflow rate is affected by the static pressure losses.
1193
+ hp_ap.cool_cap_fflow_spec = [[0.655239515, 0.511655216, -0.166894731],
1194
+ [0.618281092, 0.569060264, -0.187341356]]
1195
+ hp_ap.cool_eir_fflow_spec = [[1.639108268, -0.998953996, 0.359845728],
1196
+ [1.570774717, -0.914152018, 0.343377302]]
1197
+ hp_ap.cool_eers = calc_eers_cooling_2speed(heat_pump.cooling_efficiency_seer, hp_ap.cool_c_d, hp_ap.cool_capacity_ratios, hp_ap.cool_fan_speed_ratios, hp_ap.fan_power_rated, hp_ap.cool_eir_ft_spec, hp_ap.cool_cap_ft_spec)
1198
+ elsif hp_ap.num_speeds == 4
1199
+ # From Carrier heat pump lab testing
1200
+ hp_ap.cool_rated_airflow_rate = 411.0 # cfm/ton
1201
+ hp_ap.cool_capacity_ratios = [0.36, 0.51, 0.67, 1.0]
1202
+ hp_ap.cool_fan_speed_ratios = [0.42, 0.54, 0.68, 1.0]
1203
+ hp_ap.cool_rated_shrs_net = [1.115, 1.026, 1.013, 1.0].map { |mult| heat_pump.cooling_shr * mult }
1204
+ hp_ap.cool_cap_coeff_perf_map = [[1.6516044444444447, 0.0698916049382716, -0.0005546296296296296, -0.08870160493827162, 0.0004135802469135802, 0.00029077160493827157],
1205
+ [-6.84948049382716, 0.26946, -0.0019413580246913577, -0.03281469135802469, 0.00015694444444444442, 3.32716049382716e-05],
1206
+ [-4.53543086419753, 0.15358543209876546, -0.0009345679012345678, 0.002666913580246914, -7.993827160493826e-06, -0.00011617283950617283],
1207
+ [-3.500948395061729, 0.11738987654320988, -0.0006580246913580248, 0.007003148148148148, -2.8518518518518517e-05, -0.0001284259259259259],
1208
+ [1.8769221728395058, -0.04768641975308643, 0.0006885802469135801, 0.006643395061728395, 1.4209876543209876e-05, -0.00024043209876543206]]
1209
+ hp_ap.cool_cap_ft_spec = hp_ap.cool_cap_coeff_perf_map.select { |i| [0, 1, 2, 4].include? hp_ap.cool_cap_coeff_perf_map.index(i) }
1210
+ hp_ap.cool_cap_ft_spec_3 = hp_ap.cool_cap_coeff_perf_map.select { |i| [0, 1, 4].include? hp_ap.cool_cap_coeff_perf_map.index(i) }
1211
+ hp_ap.cool_eir_coeff_perf_map = [[2.896298765432099, -0.12487654320987657, 0.0012148148148148148, 0.04492037037037037, 8.734567901234567e-05, -0.0006348765432098764],
1212
+ [6.428076543209876, -0.20913209876543212, 0.0018521604938271604, 0.024392592592592594, 0.00019691358024691356, -0.0006012345679012346],
1213
+ [5.136356049382716, -0.1591530864197531, 0.0014151234567901232, 0.018665555555555557, 0.00020398148148148147, -0.0005407407407407407],
1214
+ [1.3823471604938273, -0.02875123456790123, 0.00038302469135802463, 0.006344814814814816, 0.00024836419753086417, -0.00047469135802469134],
1215
+ [-1.0411735802469133, 0.055261604938271605, -0.0004404320987654321, 0.0002154938271604939, 0.00017484567901234564, -0.0002017901234567901]]
1216
+ hp_ap.cool_eir_ft_spec = hp_ap.cool_eir_coeff_perf_map.select { |i| [0, 1, 2, 4].include? hp_ap.cool_eir_coeff_perf_map.index(i) }
1217
+ hp_ap.cool_eir_ft_spec_3 = hp_ap.cool_eir_coeff_perf_map.select { |i| [0, 1, 4].include? hp_ap.cool_eir_coeff_perf_map.index(i) }
1218
+ # Variable speed systems have constant flow ECM blowers, so the air handler can always achieve the design airflow rate by sacrificing blower power.
1219
+ # So we assume that there is only one corresponding airflow rate for each compressor speed.
1220
+ hp_ap.cool_eir_fflow_spec = [[1, 0, 0]] * 4
1221
+ hp_ap.cool_cap_fflow_spec = [[1, 0, 0]] * 4
1222
+ hp_ap.cap_ratio_seer_3 = hp_ap.cool_capacity_ratios.select { |i| [0, 1, 3].include? hp_ap.cool_capacity_ratios.index(i) }
1223
+ hp_ap.fan_speed_seer_3 = hp_ap.cool_fan_speed_ratios.select { |i| [0, 1, 3].include? hp_ap.cool_fan_speed_ratios.index(i) }
1224
+ hp_ap.cool_eers = calc_eers_cooling_4speed(heat_pump.cooling_efficiency_seer, hp_ap.cool_c_d, hp_ap.cap_ratio_seer_3, hp_ap.fan_speed_seer_3, hp_ap.fan_power_rated, hp_ap.cool_eir_ft_spec_3, hp_ap.cool_cap_ft_spec_3)
1637
1225
  end
1638
1226
  end
1639
1227
 
1640
- def self.get_default_ceiling_fan_power()
1641
- # Per ANSI/RESNET/ICC 301
1642
- return 42.6 # W
1643
- end
1644
-
1645
- def self.get_default_ceiling_fan_quantity(nbeds)
1228
+ def self.set_ashp_htg_curves(heat_pump)
1229
+ hp_ap = heat_pump.additional_properties
1230
+ if hp_ap.num_speeds == 1
1231
+ # From "Improved Modeling of Residential Air Conditioners and Heat Pumps for Energy Calculations", Cutler at al
1232
+ # https://www.nrel.gov/docs/fy13osti/56354.pdf
1233
+ hp_ap.heat_rated_airflow_rate = 384.1 # cfm/ton
1234
+ hp_ap.heat_capacity_ratios = [1.0]
1235
+ hp_ap.heat_fan_speed_ratios = [1.0]
1236
+ hp_ap.heat_eir_ft_spec = [[0.718398423, 0.003498178, 0.000142202, -0.005724331, 0.00014085, -0.000215321]]
1237
+ hp_ap.heat_cap_fflow_spec = [[0.694045465, 0.474207981, -0.168253446]]
1238
+ hp_ap.heat_eir_fflow_spec = [[2.185418751, -1.942827919, 0.757409168]]
1239
+ if heat_pump.heating_capacity_17F.nil?
1240
+ hp_ap.heat_cap_ft_spec = [[0.566333415, -0.000744164, -0.0000103, 0.009414634, 0.0000506, -0.00000675]]
1241
+ else
1242
+ hp_ap.heat_cap_ft_spec = calc_heat_cap_ft_spec_using_capacity_17F(heat_pump)
1243
+ end
1244
+ hp_ap.heat_cops = [calc_cop_heating_1speed(heat_pump.heating_efficiency_hspf, hp_ap.heat_c_d, hp_ap.fan_power_rated, hp_ap.heat_eir_ft_spec, hp_ap.heat_cap_ft_spec)]
1245
+ elsif hp_ap.num_speeds == 2
1246
+ # From "Improved Modeling of Residential Air Conditioners and Heat Pumps for Energy Calculations", Cutler at al
1247
+ # https://www.nrel.gov/docs/fy13osti/56354.pdf
1248
+ hp_ap.heat_rated_airflow_rate = 352.2 # cfm/ton
1249
+ hp_ap.heat_capacity_ratios = [0.72, 1.0]
1250
+ hp_ap.heat_fan_speed_ratios = [0.8, 1.0]
1251
+ hp_ap.heat_eir_ft_spec = [[0.36338171, 0.013523725, 0.000258872, -0.009450269, 0.000439519, -0.000653723],
1252
+ [0.981100941, -0.005158493, 0.000243416, -0.005274352, 0.000230742, -0.000336954]]
1253
+ hp_ap.heat_cap_fflow_spec = [[0.741466907, 0.378645444, -0.119754733],
1254
+ [0.76634609, 0.32840943, -0.094701495]]
1255
+ hp_ap.heat_eir_fflow_spec = [[2.153618211, -1.737190609, 0.584269478],
1256
+ [2.001041353, -1.58869128, 0.587593517]]
1257
+ if heat_pump.heating_capacity_17F.nil?
1258
+ hp_ap.heat_cap_ft_spec = [[0.335690634, 0.002405123, -0.0000464, 0.013498735, 0.0000499, -0.00000725],
1259
+ [0.306358843, 0.005376987, -0.0000579, 0.011645092, 0.0000591, -0.0000203]]
1260
+ else
1261
+ hp_ap.heat_cap_ft_spec = calc_heat_cap_ft_spec_using_capacity_17F(heat_pump)
1262
+ end
1263
+ hp_ap.heat_cops = calc_cops_heating_2speed(heat_pump.heating_efficiency_hspf, hp_ap.heat_c_d, hp_ap.heat_capacity_ratios, hp_ap.heat_fan_speed_ratios, hp_ap.fan_power_rated, hp_ap.heat_eir_ft_spec, hp_ap.heat_cap_ft_spec)
1264
+ elsif hp_ap.num_speeds == 4
1265
+ # From Carrier heat pump lab testing
1266
+ hp_ap.heat_rated_airflow_rate = 296.9 # cfm/ton
1267
+ hp_ap.heat_capacity_ratios = [0.33, 0.56, 1.0, 1.17]
1268
+ hp_ap.heat_fan_speed_ratios = [0.63, 0.76, 1.0, 1.19]
1269
+ hp_ap.heat_eir_ft_spec = [[0.708311527, 0.020732093, 0.000391479, -0.037640031, 0.000979937, -0.001079042],
1270
+ [0.025480155, 0.020169585, 0.000121341, -0.004429789, 0.000166472, -0.00036447],
1271
+ [0.379003189, 0.014195012, 0.0000821046, -0.008894061, 0.000151519, -0.000210299],
1272
+ [0.690404655, 0.00616619, 0.000137643, -0.009350199, 0.000153427, -0.000213258]]
1273
+ hp_ap.heat_cap_fflow_spec = [[1, 0, 0]] * 4
1274
+ hp_ap.heat_eir_fflow_spec = [[1, 0, 0]] * 4
1275
+ if heat_pump.heating_capacity_17F.nil?
1276
+ hp_ap.heat_cap_ft_spec = [[0.304192655, -0.003972566, 0.0000196432, 0.024471251, -0.000000774126, -0.0000841323],
1277
+ [0.496381324, -0.00144792, 0.0, 0.016020855, 0.0000203447, -0.0000584118],
1278
+ [0.697171186, -0.006189599, 0.0000337077, 0.014291981, 0.0000105633, -0.0000387956],
1279
+ [0.555513805, -0.001337363, -0.00000265117, 0.014328826, 0.0000163849, -0.0000480711]]
1280
+ else
1281
+ hp_ap.heat_cap_ft_spec = calc_heat_cap_ft_spec_using_capacity_17F(heat_pump)
1282
+ end
1283
+ hp_ap.heat_cops = calc_cops_heating_4speed(heat_pump.heating_efficiency_hspf, hp_ap.heat_c_d, hp_ap.heat_capacity_ratios, hp_ap.heat_fan_speed_ratios, hp_ap.fan_power_rated, hp_ap.heat_eir_ft_spec, hp_ap.heat_cap_ft_spec)
1284
+ end
1285
+ end
1286
+
1287
+ def self.set_cool_curves_room_ac(cooling_system)
1288
+ clg_ap = cooling_system.additional_properties
1289
+
1290
+ # From "Improved Modeling of Residential Air Conditioners and Heat Pumps for Energy Calculations", Cutler at al
1291
+ # https://www.nrel.gov/docs/fy13osti/56354.pdf
1292
+ clg_ap.cool_cap_ft_spec = [[3.68637657, -0.098352478, 0.000956357, 0.005838141, -0.0000127, -0.000131702]]
1293
+ clg_ap.cool_eir_ft_spec = [[-3.437356399, 0.136656369, -0.001049231, -0.0079378, 0.000185435, -0.0001441]]
1294
+ clg_ap.cool_cap_fflow_spec = [[1, 0, 0]]
1295
+ clg_ap.cool_eir_fflow_spec = [[1, 0, 0]]
1296
+ end
1297
+
1298
+ def self.set_cool_curves_mshp(heat_pump, num_speeds)
1299
+ hp_ap = heat_pump.additional_properties
1300
+
1301
+ # From Daikin mini-split lab testing
1302
+ hp_ap.cool_cap_ft_spec = [[0.7531983499655835, 0.003618193903031667, 0.0, 0.006574385031351544, -6.87181191015432e-05, 0.0]] * num_speeds
1303
+ hp_ap.cool_eir_ft_spec = [[-0.06376924779982301, -0.0013360593470367282, 1.413060577993827e-05, 0.019433076486584752, -4.91395947154321e-05, -4.909341249475308e-05]] * num_speeds
1304
+ hp_ap.cool_cap_fflow_spec = [[1, 0, 0]] * num_speeds
1305
+ hp_ap.cool_eir_fflow_spec = [[1, 0, 0]] * num_speeds
1306
+
1307
+ hp_ap.cool_min_capacity_ratio = 0.4 # frac
1308
+ hp_ap.cool_max_capacity_ratio = 1.2 # frac
1309
+ hp_ap.cool_min_cfm_per_ton = 200.0 / hp_ap.cool_min_capacity_ratio # Convert cfm/ton of nominal rated capacity to cfm/ton of min capacity
1310
+ hp_ap.cool_max_cfm_per_ton = 425.0 / hp_ap.cool_max_capacity_ratio # Convert cfm/ton of nominal rated capacity to cfm/ton of max capacity
1311
+ end
1312
+
1313
+ def self.set_heat_curves_mshp(heat_pump, num_speeds)
1314
+ hp_ap = heat_pump.additional_properties
1315
+
1316
+ # From Daikin mini-split lab testing
1317
+ hp_ap.heat_eir_ft_spec = [[0.9999941697687026, 0.004684593830254383, 5.901286675833333e-05, -0.0028624467783091973, 1.3041120194135802e-05, -0.00016172918478765433]] * num_speeds
1318
+ hp_ap.heat_cap_fflow_spec = [[1, 0, 0]] * num_speeds
1319
+ hp_ap.heat_eir_fflow_spec = [[1, 0, 0]] * num_speeds
1320
+
1321
+ # Derive coefficients from user input for capacity retention at outdoor drybulb temperature X [C].
1322
+ if heat_pump.heating_capacity_17F.nil? || ((heat_pump.heating_capacity_17F == 0) && (heat_pump.heating_capacity == 0))
1323
+ cap_retention_frac = 0.25 # frac
1324
+ cap_retention_temp = -5.0 # deg-F
1325
+ else
1326
+ cap_retention_frac = heat_pump.heating_capacity_17F / heat_pump.heating_capacity
1327
+ cap_retention_temp = 17.0 # deg-F
1328
+ end
1329
+
1330
+ # Biquadratic: capacity multiplier = a + b*IAT + c*IAT^2 + d*OAT + e*OAT^2 + f*IAT*OAT
1331
+ x_A = UnitConversions.convert(cap_retention_temp, 'F', 'C')
1332
+ y_A = cap_retention_frac
1333
+ x_B = UnitConversions.convert(47.0, 'F', 'C') # 47F is the rating point
1334
+ y_B = 1.0 # Maximum capacity factor is 1 at the rating point, by definition (this is maximum capacity, not nominal capacity)
1335
+ oat_slope = (y_B - y_A) / (x_B - x_A)
1336
+ oat_intercept = y_A - (x_A * oat_slope)
1337
+
1338
+ # Coefficients for the indoor temperature relationship are retained from the generic curve (Daikin lab data).
1339
+ iat_slope = -0.010386676170938
1340
+ iat_intercept = 0.219274275
1341
+ a = oat_intercept + iat_intercept
1342
+ b = iat_slope
1343
+ c = 0
1344
+ d = oat_slope
1345
+ e = 0
1346
+ f = 0
1347
+ hp_ap.heat_cap_ft_spec = [HVAC.convert_curve_biquadratic([a, b, c, d, e, f], false)] * num_speeds
1348
+
1349
+ hp_ap.heat_min_capacity_ratio = 0.3 # frac
1350
+ hp_ap.heat_max_capacity_ratio = 1.2 # frac
1351
+ hp_ap.heat_min_cfm_per_ton = 200.0 / hp_ap.heat_min_capacity_ratio # Convert cfm/ton of nominal rated capacity to cfm/ton of min capacity
1352
+ hp_ap.heat_max_cfm_per_ton = 400.0 / hp_ap.heat_max_capacity_ratio # Convert cfm/ton of nominal rated capacity to cfm/ton of min capacity
1353
+ end
1354
+
1355
+ def self.set_curves_gshp(heat_pump)
1356
+ hp_ap = heat_pump.additional_properties
1357
+
1358
+ # E+ equation fit coil coefficients generated following approach in Tang's thesis:
1359
+ # See Appendix B of https://hvac.okstate.edu/sites/default/files/pubs/theses/MS/27-Tang_Thesis_05.pdf
1360
+ # Coefficients generated by catalog data: https://files.climatemaster.com/Genesis-GS-Series-Product-Catalog.pdf, p180
1361
+ # Data point taken as rated condition:
1362
+ # EWT: 80F EAT:80/67F, AFR: 1200cfm, WFR: 4.5gpm
1363
+ hp_ap.cool_cap_ft_spec = [[-1.57177156131221, 4.60343712716819, -2.15976622898044, 0.0590964827802021, 0.0194696644460315]]
1364
+ hp_ap.cool_power_ft_spec = [[-4.42471086639888, 0.658017281046304, 4.37331801294626, 0.174096187531254, -0.0526514790164159]]
1365
+ hp_ap.cool_sh_ft_spec = [[4.54172823345154, 14.7653304889134, -18.3541272090485, -0.74401391092935, 0.545560799548833, 0.0182620032235494]]
1366
+ hp_ap.cool_rated_shrs_gross = [heat_pump.cooling_shr]
1367
+ # FUTURE: Reconcile these fan/pump adjustments with ANSI/RESNET/ICC 301-2019 Section 4.4.5
1368
+ fan_adjust_kw = UnitConversions.convert(400.0, 'Btu/hr', 'ton') * UnitConversions.convert(1.0, 'cfm', 'm^3/s') * 1000.0 * 0.35 * 249.0 / 300.0 # Adjustment per ISO 13256-1 Internal pressure drop across heat pump assumed to be 0.5 in. w.g.
1369
+ pump_adjust_kw = UnitConversions.convert(3.0, 'Btu/hr', 'ton') * UnitConversions.convert(1.0, 'gal/min', 'm^3/s') * 1000.0 * 6.0 * 2990.0 / 3000.0 # Adjustment per ISO 13256-1 Internal Pressure drop across heat pump coil assumed to be 11ft w.g.
1370
+ cool_eir = UnitConversions.convert((1.0 - heat_pump.cooling_efficiency_eer * (fan_adjust_kw + pump_adjust_kw)) / (heat_pump.cooling_efficiency_eer * (1.0 + UnitConversions.convert(fan_adjust_kw, 'Wh', 'Btu'))), 'Wh', 'Btu')
1371
+ hp_ap.cool_rated_eirs = [cool_eir]
1372
+
1373
+ # E+ equation fit coil coefficients from Tang's thesis:
1374
+ # See Appendix B Figure B.3 of https://hvac.okstate.edu/sites/default/files/pubs/theses/MS/27-Tang_Thesis_05.pdf
1375
+ # Coefficients generated by catalog data
1376
+ hp_ap.heat_cap_ft_spec = [[-5.12650150, -0.93997630, 7.21443206, 0.121065721, 0.051809805]]
1377
+ hp_ap.heat_power_ft_spec = [[-7.73235249, 6.43390775, 2.29152262, -0.175598629, 0.005888871]]
1378
+ heat_eir = (1.0 - heat_pump.heating_efficiency_cop * (fan_adjust_kw + pump_adjust_kw)) / (heat_pump.heating_efficiency_cop * (1.0 - fan_adjust_kw))
1379
+ hp_ap.heat_rated_eirs = [heat_eir]
1380
+ end
1381
+
1382
+ def self.get_default_compressor_type(hvac_type, seer)
1383
+ if [HPXML::HVACTypeCentralAirConditioner,
1384
+ HPXML::HVACTypeHeatPumpAirToAir].include? hvac_type
1385
+ if seer <= 15
1386
+ return HPXML::HVACCompressorTypeSingleStage
1387
+ elsif seer <= 21
1388
+ return HPXML::HVACCompressorTypeTwoStage
1389
+ elsif seer > 21
1390
+ return HPXML::HVACCompressorTypeVariableSpeed
1391
+ end
1392
+ end
1393
+ return
1394
+ end
1395
+
1396
+ def self.get_default_ceiling_fan_power()
1397
+ # Per ANSI/RESNET/ICC 301
1398
+ return 42.6 # W
1399
+ end
1400
+
1401
+ def self.get_default_ceiling_fan_quantity(nbeds)
1646
1402
  # Per ANSI/RESNET/ICC 301
1647
1403
  return nbeds + 1
1648
1404
  end
@@ -1740,12 +1496,12 @@ class HVAC
1740
1496
  pump_mfr_sensor.setKeyName(pump.name.to_s)
1741
1497
 
1742
1498
  # Internal variable
1743
- pump_rated_mfr_var = OpenStudio::Model::EnergyManagementSystemInternalVariable.new(model, 'Pump Maximum Mass Flow Rate')
1499
+ pump_rated_mfr_var = OpenStudio::Model::EnergyManagementSystemInternalVariable.new(model, EPlus::EMSIntVarPumpMFR)
1744
1500
  pump_rated_mfr_var.setName("#{pump.name} rated mfr")
1745
1501
  pump_rated_mfr_var.setInternalDataIndexKeyName(pump.name.to_s)
1746
1502
 
1747
1503
  # Actuator
1748
- pump_pressure_rise_act = OpenStudio::Model::EnergyManagementSystemActuator.new(pump, 'Pump', 'Pump Pressure Rise')
1504
+ pump_pressure_rise_act = OpenStudio::Model::EnergyManagementSystemActuator.new(pump, *EPlus::EMSActuatorPumpPressureRise)
1749
1505
  pump_pressure_rise_act.setName("#{pump.name} pressure rise act")
1750
1506
 
1751
1507
  # Program
@@ -1774,11 +1530,11 @@ class HVAC
1774
1530
  hvac_objects = []
1775
1531
 
1776
1532
  if fan_or_pump.is_a?(OpenStudio::Model::FanOnOff) || fan_or_pump.is_a?(OpenStudio::Model::FanVariableVolume)
1777
- fan_or_pump_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Fan Electric Energy')
1533
+ fan_or_pump_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, "Fan #{EPlus::FuelTypeElectricity} Energy")
1778
1534
  elsif fan_or_pump.is_a? OpenStudio::Model::PumpVariableSpeed
1779
- fan_or_pump_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Pump Electric Energy')
1535
+ fan_or_pump_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, "Pump #{EPlus::FuelTypeElectricity} Energy")
1780
1536
  elsif fan_or_pump.is_a? OpenStudio::Model::ElectricEquipment
1781
- fan_or_pump_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Electric Equipment Electric Energy')
1537
+ fan_or_pump_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, "Electric Equipment #{EPlus::FuelTypeElectricity} Energy")
1782
1538
  else
1783
1539
  fail "Unexpected fan/pump object '#{fan_or_pump.name}'."
1784
1540
  end
@@ -1792,7 +1548,7 @@ class HVAC
1792
1548
  if clg_object.is_a? OpenStudio::Model::EvaporativeCoolerDirectResearchSpecial
1793
1549
  var = 'Evaporative Cooler Water Volume'
1794
1550
  else
1795
- var = 'Cooling Coil Electric Energy'
1551
+ var = "Cooling Coil #{EPlus::FuelTypeElectricity} Energy"
1796
1552
  end
1797
1553
  clg_object_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
1798
1554
  clg_object_sensor.setName("#{clg_object.name} s")
@@ -1803,9 +1559,9 @@ class HVAC
1803
1559
  if htg_object.nil?
1804
1560
  htg_object_sensor = nil
1805
1561
  else
1806
- var = "Heating Coil #{EPlus.output_fuel_map(EPlus::FuelTypeElectricity)} Energy"
1562
+ var = "Heating Coil #{EPlus::FuelTypeElectricity} Energy"
1807
1563
  if htg_object.is_a? OpenStudio::Model::CoilHeatingGas
1808
- var = "Heating Coil #{EPlus.output_fuel_map(htg_object.fuelType)} Energy"
1564
+ var = "Heating Coil #{htg_object.fuelType} Energy"
1809
1565
  elsif htg_object.is_a? OpenStudio::Model::ZoneHVACBaseboardConvectiveWater
1810
1566
  var = 'Baseboard Total Heating Energy'
1811
1567
  elsif htg_object.is_a? OpenStudio::Model::ZoneHVACFourPipeFanCoil
@@ -1821,9 +1577,9 @@ class HVAC
1821
1577
  if backup_htg_object.nil?
1822
1578
  backup_htg_object_sensor = nil
1823
1579
  else
1824
- var = "Heating Coil #{EPlus.output_fuel_map(EPlus::FuelTypeElectricity)} Energy"
1580
+ var = "Heating Coil #{EPlus::FuelTypeElectricity} Energy"
1825
1581
  if backup_htg_object.is_a? OpenStudio::Model::CoilHeatingGas
1826
- var = "Heating Coil #{EPlus.output_fuel_map(backup_htg_object.fuelType)} Energy"
1582
+ var = "Heating Coil #{backup_htg_object.fuelType} Energy"
1827
1583
  end
1828
1584
 
1829
1585
  backup_htg_object_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var)
@@ -1835,32 +1591,36 @@ class HVAC
1835
1591
  sensors = { 'clg' => clg_object_sensor,
1836
1592
  'primary_htg' => htg_object_sensor,
1837
1593
  'backup_htg' => backup_htg_object_sensor }
1594
+ sensors = sensors.select { |m, s| !s.nil? }
1838
1595
 
1839
1596
  fan_or_pump_var = fan_or_pump.name.to_s.gsub(' ', '_')
1840
1597
 
1841
1598
  # Disaggregate electric fan/pump energy
1842
1599
  fan_or_pump_program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
1843
1600
  fan_or_pump_program.setName("#{fan_or_pump_var} disaggregate program")
1844
- sensors.each do |mode, sensor|
1845
- next if sensor.nil?
1846
-
1847
- fan_or_pump_program.addLine("Set #{fan_or_pump_var}_#{mode} = 0")
1848
- end
1849
- i = 0
1850
- sensors.each do |mode, sensor|
1851
- next if sensor.nil?
1852
-
1853
- if i == 0
1854
- fan_or_pump_program.addLine("If #{sensor.name} > 0")
1855
- elsif i == 2
1856
- fan_or_pump_program.addLine('Else')
1857
- else
1858
- fan_or_pump_program.addLine("ElseIf #{sensor.name} > 0")
1601
+ if htg_object.is_a?(OpenStudio::Model::ZoneHVACBaseboardConvectiveWater) || htg_object.is_a?(OpenStudio::Model::ZoneHVACFourPipeFanCoil)
1602
+ # Pump may occassionally run when baseboard isn't, so just assign all pump energy here
1603
+ mode, sensor = sensors.first
1604
+ if (sensors.size != 1) || (mode != 'primary_htg')
1605
+ fail 'Unexpected situation.'
1859
1606
  end
1860
1607
  fan_or_pump_program.addLine(" Set #{fan_or_pump_var}_#{mode} = #{fan_or_pump_sensor.name}")
1861
- i += 1
1608
+ else
1609
+ sensors.each do |mode, sensor|
1610
+ fan_or_pump_program.addLine("Set #{fan_or_pump_var}_#{mode} = 0")
1611
+ end
1612
+ sensors.each_with_index do |(mode, sensor), i|
1613
+ if i == 0
1614
+ fan_or_pump_program.addLine("If #{sensor.name} > 0")
1615
+ elsif i == 2
1616
+ fan_or_pump_program.addLine('Else')
1617
+ else
1618
+ fan_or_pump_program.addLine("ElseIf #{sensor.name} > 0")
1619
+ end
1620
+ fan_or_pump_program.addLine(" Set #{fan_or_pump_var}_#{mode} = #{fan_or_pump_sensor.name}")
1621
+ end
1622
+ fan_or_pump_program.addLine('EndIf')
1862
1623
  end
1863
- fan_or_pump_program.addLine('EndIf')
1864
1624
  hvac_objects << fan_or_pump_program
1865
1625
 
1866
1626
  fan_or_pump_program_calling_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
@@ -1882,12 +1642,6 @@ class HVAC
1882
1642
  fan_or_pump_ems_output_var.setEMSProgramOrSubroutineName(fan_or_pump_program)
1883
1643
  fan_or_pump_ems_output_var.setUnits('J')
1884
1644
  hvac_objects << fan_or_pump_ems_output_var
1885
-
1886
- # Used by HEScore
1887
- # TODO: Move to HEScore project or reporting measure
1888
- outputVariable = OpenStudio::Model::OutputVariable.new(fan_or_pump_ems_output_var.name.to_s, model)
1889
- outputVariable.setReportingFrequency('monthly')
1890
- outputVariable.setKeyValue('*')
1891
1645
  end
1892
1646
 
1893
1647
  return hvac_objects
@@ -1900,7 +1654,7 @@ class HVAC
1900
1654
  dehumidifier_sens_htg = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Dehumidifier Sensible Heating Rate')
1901
1655
  dehumidifier_sens_htg.setName("#{zone_hvac.name} sens htg")
1902
1656
  dehumidifier_sens_htg.setKeyName(zone_hvac.name.to_s)
1903
- dehumidifier_power = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Dehumidifier Electric Power')
1657
+ dehumidifier_power = OpenStudio::Model::EnergyManagementSystemSensor.new(model, "Zone Dehumidifier #{EPlus::FuelTypeElectricity} Rate")
1904
1658
  dehumidifier_power.setName("#{zone_hvac.name} power htg")
1905
1659
  dehumidifier_power.setKeyName(zone_hvac.name.to_s)
1906
1660
 
@@ -1916,7 +1670,7 @@ class HVAC
1916
1670
  dehumidifier_load_adj.setSpace(living_space)
1917
1671
  dehumidifier_load_adj.setSchedule(model.alwaysOnDiscreteSchedule)
1918
1672
 
1919
- dehumidifier_load_adj_act = OpenStudio::Model::EnergyManagementSystemActuator.new(dehumidifier_load_adj, 'OtherEquipment', 'Power Level')
1673
+ dehumidifier_load_adj_act = OpenStudio::Model::EnergyManagementSystemActuator.new(dehumidifier_load_adj, *EPlus::EMSActuatorOtherEquipmentPower)
1920
1674
  dehumidifier_load_adj_act.setName("#{zone_hvac.name} sens htg adj act")
1921
1675
 
1922
1676
  # EMS program
@@ -1954,16 +1708,14 @@ class HVAC
1954
1708
  htg_supp_coil.setGasBurnerEfficiency(efficiency)
1955
1709
  htg_supp_coil.setParasiticElectricLoad(0)
1956
1710
  htg_supp_coil.setParasiticGasLoad(0)
1957
- htg_supp_coil.setFuelType(EPlus.input_fuel_map(fuel))
1711
+ htg_supp_coil.setFuelType(EPlus.fuel_type(fuel))
1958
1712
  end
1713
+ htg_supp_coil.setNominalCapacity(UnitConversions.convert(capacity, 'Btu/hr', 'W'))
1959
1714
  htg_supp_coil.setName(obj_name + ' ' + Constants.ObjectNameBackupHeatingCoil)
1960
- if not capacity.nil?
1961
- htg_supp_coil.setNominalCapacity(UnitConversions.convert([capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
1962
- end
1963
1715
  return htg_supp_coil
1964
1716
  end
1965
1717
 
1966
- def self.create_supply_fan(model, obj_name, num_speeds, fan_power_installed)
1718
+ def self.create_supply_fan(model, obj_name, num_speeds, fan_watts_per_cfm, fan_cfm)
1967
1719
  if num_speeds == 1
1968
1720
  fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
1969
1721
  else
@@ -1971,37 +1723,35 @@ class HVAC
1971
1723
  fan_eff_curve = create_curve_cubic(model, [0, 1, 0, 0], obj_name + ' fan eff curve', 0, 1, 0.01, 1)
1972
1724
  fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule, fan_power_curve, fan_eff_curve)
1973
1725
  end
1974
- if fan_power_installed > 0
1975
- fan_eff = 0.75 # Overall Efficiency of the Fan, Motor and Drive
1976
- fan.setFanEfficiency(fan_eff)
1977
- fan.setPressureRise(calc_fan_pressure_rise(fan_eff, fan_power_installed))
1978
- else
1979
- fan.setFanEfficiency(1)
1980
- fan.setPressureRise(0)
1981
- end
1726
+ set_fan_power(fan, fan_watts_per_cfm)
1982
1727
  fan.setName(obj_name + ' supply fan')
1983
1728
  fan.setEndUseSubcategory('supply fan')
1984
1729
  fan.setMotorEfficiency(1.0)
1985
1730
  fan.setMotorInAirstreamFraction(1.0)
1731
+ fan.setMaximumFlowRate(UnitConversions.convert(fan_cfm, 'cfm', 'm^3/s'))
1986
1732
  return fan
1987
1733
  end
1988
1734
 
1989
- def self.create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, supp_max_temp = nil, htg_cfm: nil, clg_cfm: nil)
1735
+ def self.create_air_loop_unitary_system(model, obj_name, fan, htg_coil, clg_coil, htg_supp_coil, htg_cfm, clg_cfm, supp_max_temp = nil)
1990
1736
  air_loop_unitary = OpenStudio::Model::AirLoopHVACUnitarySystem.new(model)
1991
1737
  air_loop_unitary.setName(obj_name + ' unitary system')
1992
1738
  air_loop_unitary.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
1993
1739
  air_loop_unitary.setSupplyFan(fan)
1994
1740
  air_loop_unitary.setFanPlacement('BlowThrough')
1995
1741
  air_loop_unitary.setSupplyAirFanOperatingModeSchedule(model.alwaysOffDiscreteSchedule)
1742
+ air_loop_unitary.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
1996
1743
  if htg_coil.nil?
1997
1744
  air_loop_unitary.setSupplyAirFlowRateDuringHeatingOperation(0.0)
1998
1745
  else
1999
1746
  air_loop_unitary.setHeatingCoil(htg_coil)
1747
+ air_loop_unitary.setSupplyAirFlowRateDuringHeatingOperation(UnitConversions.convert(htg_cfm, 'cfm', 'm^3/s'))
2000
1748
  end
1749
+ air_loop_unitary.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
2001
1750
  if clg_coil.nil?
2002
1751
  air_loop_unitary.setSupplyAirFlowRateDuringCoolingOperation(0.0)
2003
1752
  else
2004
1753
  air_loop_unitary.setCoolingCoil(clg_coil)
1754
+ air_loop_unitary.setSupplyAirFlowRateDuringCoolingOperation(UnitConversions.convert(clg_cfm, 'cfm', 'm^3/s'))
2005
1755
  end
2006
1756
  if htg_supp_coil.nil?
2007
1757
  air_loop_unitary.setMaximumSupplyAirTemperature(UnitConversions.convert(120.0, 'F', 'C'))
@@ -2011,23 +1761,16 @@ class HVAC
2011
1761
  air_loop_unitary.setMaximumOutdoorDryBulbTemperatureforSupplementalHeaterOperation(UnitConversions.convert(supp_max_temp, 'F', 'C'))
2012
1762
  end
2013
1763
  air_loop_unitary.setSupplyAirFlowRateWhenNoCoolingorHeatingisRequired(0)
2014
- if not clg_cfm.nil? # Hidden feature; used only for HERS DSE test
2015
- air_loop_unitary.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
2016
- air_loop_unitary.setSupplyAirFlowRateDuringCoolingOperation(UnitConversions.convert(clg_cfm, 'cfm', 'm^3/s'))
2017
- end
2018
- if not htg_cfm.nil? # Hidden feature; used only for HERS DSE test
2019
- air_loop_unitary.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
2020
- air_loop_unitary.setSupplyAirFlowRateDuringHeatingOperation(UnitConversions.convert(htg_cfm, 'cfm', 'm^3/s'))
2021
- end
2022
1764
  return air_loop_unitary
2023
1765
  end
2024
1766
 
2025
- def self.create_air_loop(model, obj_name, system, control_zone, sequential_heat_load_frac, sequential_cool_load_frac)
1767
+ def self.create_air_loop(model, obj_name, system, control_zone, sequential_heat_load_frac, sequential_cool_load_frac, airflow_cfm)
2026
1768
  air_loop = OpenStudio::Model::AirLoopHVAC.new(model)
2027
1769
  air_loop.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
2028
1770
  air_loop.setName(obj_name + ' airloop')
2029
1771
  air_loop.zoneSplitter.setName(obj_name + ' zone splitter')
2030
1772
  air_loop.zoneMixer.setName(obj_name + ' zone mixer')
1773
+ air_loop.setDesignSupplyAirFlowRate(UnitConversions.convert(airflow_cfm, 'cfm', 'm^3/s'))
2031
1774
  system.addToNode(air_loop.supplyInletNode)
2032
1775
 
2033
1776
  if system.is_a? OpenStudio::Model::AirLoopHVACUnitarySystem
@@ -2038,6 +1781,7 @@ class HVAC
2038
1781
  air_terminal.setConstantMinimumAirFlowFraction(0)
2039
1782
  air_terminal.setFixedMinimumAirFlowRate(0)
2040
1783
  end
1784
+ air_terminal.setMaximumAirFlowRate(UnitConversions.convert(airflow_cfm, 'cfm', 'm^3/s'))
2041
1785
  air_terminal.setName(obj_name + ' terminal')
2042
1786
  air_loop.multiAddBranchForZone(control_zone, air_terminal)
2043
1787
 
@@ -2047,10 +1791,14 @@ class HVAC
2047
1791
  return air_loop
2048
1792
  end
2049
1793
 
2050
- def self.apply_dehumidifier_ief_to_ef_inputs(w_coeff, ef_coeff, ief, water_removal_rate)
1794
+ def self.apply_dehumidifier_ief_to_ef_inputs(dh_type, w_coeff, ef_coeff, ief, water_removal_rate)
2051
1795
  # Shift inputs under IEF test conditions to E+ supported EF test conditions
2052
1796
  # test conditions
2053
- ief_db = UnitConversions.convert(65.0, 'F', 'C') # degree C
1797
+ if dh_type == HPXML::DehumidifierTypePortable
1798
+ ief_db = UnitConversions.convert(65.0, 'F', 'C') # degree C
1799
+ elsif dh_type == HPXML::DehumidifierTypeWholeHome
1800
+ ief_db = UnitConversions.convert(73.0, 'F', 'C') # degree C
1801
+ end
2054
1802
  rh = 60.0 # for both EF and IEF test conditions, %
2055
1803
 
2056
1804
  # Independent variables applied to curve equations
@@ -2069,9 +1817,10 @@ class HVAC
2069
1817
  return ef_input, water_removal_rate_input
2070
1818
  end
2071
1819
 
2072
- def self.get_electric_auxiliary_energy(heating_system, furnace_capacity_kbtuh = nil)
2073
- # Get boiler/furnace EAE
2074
-
1820
+ def self.get_default_boiler_eae(heating_system)
1821
+ if heating_system.heating_system_type != HPXML::HVACTypeBoiler
1822
+ return
1823
+ end
2075
1824
  if not heating_system.electric_auxiliary_energy.nil?
2076
1825
  return heating_system.electric_auxiliary_energy
2077
1826
  end
@@ -2079,82 +1828,41 @@ class HVAC
2079
1828
  # From ANSI/RESNET/ICC 301-2019 Standard
2080
1829
  fuel = heating_system.heating_system_fuel
2081
1830
 
2082
- if heating_system.heating_system_type == HPXML::HVACTypeBoiler
2083
- if heating_system.is_shared_system
2084
- distribution_system = heating_system.distribution_system
2085
- distribution_type = distribution_system.distribution_system_type
1831
+ if heating_system.is_shared_system
1832
+ distribution_system = heating_system.distribution_system
1833
+ distribution_type = distribution_system.distribution_system_type
2086
1834
 
2087
- if distribution_type == HPXML::HVACDistributionTypeHydronic
2088
- # Shared boiler w/ baseboard/radiators/etc
2089
- if heating_system.shared_loop_watts.nil?
2090
- return 220.0 # kWh/yr, per ANSI/RESNET/ICC 301-2019 Table 4.5.2(5)
2091
- else
2092
- sp_kw = UnitConversions.convert(heating_system.shared_loop_watts, 'W', 'kW')
2093
- n_dweq = heating_system.number_of_units_served.to_f
2094
- aux_in = 0.0
2095
- end
2096
- elsif distribution_type == HPXML::HVACDistributionTypeHydronicAndAir
2097
- hydronic_and_air_type = distribution_system.hydronic_and_air_type
2098
- if hydronic_and_air_type == HPXML::HydronicAndAirTypeFanCoil
2099
- # Shared boiler w/ fan coil
2100
- if heating_system.shared_loop_watts.nil? || heating_system.fan_coil_watts.nil?
2101
- return 438.0 # kWh/yr, per ANSI/RESNET/ICC 301-2019 Table 4.5.2(5)
2102
- else
2103
- sp_kw = UnitConversions.convert(heating_system.shared_loop_watts, 'W', 'kW')
2104
- n_dweq = heating_system.number_of_units_served.to_f
2105
- aux_in = UnitConversions.convert(heating_system.fan_coil_watts, 'W', 'kW')
2106
- end
2107
- elsif hydronic_and_air_type == HPXML::HydronicAndAirTypeWaterLoopHeatPump
2108
- # Shared boiler w/ WLHP
2109
- if heating_system.shared_loop_watts.nil?
2110
- return 265.0 # kWh/yr, per ANSI/RESNET/ICC 301-2019 Table 4.5.2(5)
2111
- else
2112
- sp_kw = UnitConversions.convert(heating_system.shared_loop_watts, 'W', 'kW')
2113
- n_dweq = heating_system.number_of_units_served.to_f
2114
- aux_in = 0.0 # ANSI/RESNET/ICC 301-2019 Section 4.4.7.2
2115
- end
2116
- else
2117
- fail "Unexpected distribution type '#{hydronic_and_air_type}' for shared boiler."
2118
- end
1835
+ if not heating_system.shared_loop_watts.nil?
1836
+ sp_kw = UnitConversions.convert(heating_system.shared_loop_watts, 'W', 'kW')
1837
+ n_dweq = heating_system.number_of_units_served.to_f
1838
+ if distribution_system.air_type == HPXML::AirTypeFanCoil
1839
+ aux_in = UnitConversions.convert(heating_system.fan_coil_watts, 'W', 'kW')
2119
1840
  else
2120
- fail "Unexpected distribution type '#{distribution_type}' for shared boiler."
1841
+ aux_in = 0.0 # ANSI/RESNET/ICC 301-2019 Section 4.4.7.2
2121
1842
  end
2122
-
2123
1843
  # ANSI/RESNET/ICC 301-2019 Equation 4.4-5
2124
- return ((sp_kw / n_dweq) + aux_in) * 2080.0 # kWh/yr
2125
-
2126
- else # In-unit boilers
2127
-
2128
- if [HPXML::FuelTypeNaturalGas,
2129
- HPXML::FuelTypePropane,
2130
- HPXML::FuelTypeElectricity,
2131
- HPXML::FuelTypeWoodCord,
2132
- HPXML::FuelTypeWoodPellets].include? fuel
2133
- return 170.0 # kWh/yr
2134
- elsif [HPXML::FuelTypeOil,
2135
- HPXML::FuelTypeOil1,
2136
- HPXML::FuelTypeOil2,
2137
- HPXML::FuelTypeOil4,
2138
- HPXML::FuelTypeOil5or6,
2139
- HPXML::FuelTypeDiesel,
2140
- HPXML::FuelTypeKerosene,
2141
- HPXML::FuelTypeCoal,
2142
- HPXML::FuelTypeCoalAnthracite,
2143
- HPXML::FuelTypeCoalBituminous,
2144
- HPXML::FuelTypeCoke].include? fuel
2145
- return 330.0 # kWh/yr
1844
+ return (((sp_kw / n_dweq) + aux_in) * 2080.0).round(2) # kWh/yr
1845
+ elsif distribution_type == HPXML::HVACDistributionTypeHydronic
1846
+ # kWh/yr, per ANSI/RESNET/ICC 301-2019 Table 4.5.2(5)
1847
+ if distribution_system.hydronic_type == HPXML::HydronicTypeWaterLoop # Shared boiler w/ WLHP
1848
+ return 265.0
1849
+ else # Shared boiler w/ baseboard/radiators/etc
1850
+ return 220.0
1851
+ end
1852
+ elsif distribution_type == HPXML::HVACDistributionTypeAir
1853
+ if distribution_system.air_type == HPXML::AirTypeFanCoil # Shared boiler w/ fan coil
1854
+ return 438.0
2146
1855
  end
2147
-
2148
1856
  end
2149
- elsif heating_system.heating_system_type == HPXML::HVACTypeFurnace
2150
1857
 
2151
- # Furnaces
1858
+ else # In-unit boilers
1859
+
2152
1860
  if [HPXML::FuelTypeNaturalGas,
2153
1861
  HPXML::FuelTypePropane,
2154
1862
  HPXML::FuelTypeElectricity,
2155
1863
  HPXML::FuelTypeWoodCord,
2156
1864
  HPXML::FuelTypeWoodPellets].include? fuel
2157
- return 149.0 + 10.3 * furnace_capacity_kbtuh # kWh/yr
1865
+ return 170.0 # kWh/yr
2158
1866
  elsif [HPXML::FuelTypeOil,
2159
1867
  HPXML::FuelTypeOil1,
2160
1868
  HPXML::FuelTypeOil2,
@@ -2166,14 +1874,15 @@ class HVAC
2166
1874
  HPXML::FuelTypeCoalAnthracite,
2167
1875
  HPXML::FuelTypeCoalBituminous,
2168
1876
  HPXML::FuelTypeCoke].include? fuel
2169
- return 439.0 + 5.5 * furnace_capacity_kbtuh # kWh/yr
1877
+ return 330.0 # kWh/yr
2170
1878
  end
2171
1879
 
2172
1880
  end
2173
- return 0.0
2174
1881
  end
2175
1882
 
2176
- def self.calc_heat_cap_ft_spec_using_capacity_17F(num_speeds, heat_pump)
1883
+ def self.calc_heat_cap_ft_spec_using_capacity_17F(heat_pump)
1884
+ num_speeds = heat_pump.additional_properties.num_speeds
1885
+
2177
1886
  # Indoor temperature slope and intercept used if Q_17 is specified (derived using heat_cap_ft_spec)
2178
1887
  # NOTE: Using Q_17 assumes the same curve for all speeds
2179
1888
  if num_speeds == 1
@@ -2190,7 +1899,11 @@ class HVAC
2190
1899
  # Derive coefficients from user input for heating capacity at 47F and 17F
2191
1900
  # Biquadratic: capacity multiplier = a + b*IAT + c*IAT^2 + d*OAT + e*OAT^2 + f*IAT*OAT
2192
1901
  x_A = 17.0
2193
- y_A = heat_pump.heating_capacity_17F / heat_pump.heating_capacity
1902
+ if heat_pump.heating_capacity > 0
1903
+ y_A = heat_pump.heating_capacity_17F / heat_pump.heating_capacity
1904
+ else
1905
+ y_A = 0.5 # Arbitrary
1906
+ end
2194
1907
  x_B = 47.0 # 47F is the rating point
2195
1908
  y_B = 1.0
2196
1909
 
@@ -2219,22 +1932,18 @@ class HVAC
2219
1932
  return ((1.0 - 3.412 * (fan_power_rated * cfm_per_btuh)) / (eir / 3.412 + (fan_power_rated * cfm_per_btuh)))
2220
1933
  end
2221
1934
 
2222
- def self.calc_eers_from_eir_2speed(eer_2, fan_power_rated, is_heat_pump)
2223
- # Returns low and high stage eer A given high stage eer A
1935
+ def self.calc_eers_from_eir_2speed(eer_2, fan_power_rated)
1936
+ # Returns low and high stage EER A given high stage EER A
2224
1937
 
2225
1938
  eir_2_a = calc_eir_from_eer(eer_2, fan_power_rated)
2226
1939
 
2227
- if not is_heat_pump
2228
- eir_1_a = 0.8691 * eir_2_a + 0.0127 # Relationship derived using Dylan's data for two stage air conditioners
2229
- else
2230
- eir_1_a = 0.8887 * eir_2_a + 0.0083 # Relationship derived using Dylan's data for two stage heat pumps
2231
- end
1940
+ eir_1_a = 0.8887 * eir_2_a + 0.0083 # Relationship derived using Dylan's data for two stage heat pumps
2232
1941
 
2233
1942
  return [calc_eer_from_eir(eir_1_a, fan_power_rated), eer_2]
2234
1943
  end
2235
1944
 
2236
1945
  def self.calc_eers_from_eir_4speed(eer_nom, fan_power_rated, calc_type = 'seer')
2237
- # Returns eer A at minimum, intermediate, and nominal speed given eer A (and a fourth speed if calc_type != 'seer')
1946
+ # Returns EER A at minimum, intermediate, and nominal speed given EER A (and a fourth speed if calc_type != 'seer')
2238
1947
 
2239
1948
  eir_nom = calc_eir_from_eer(eer_nom, fan_power_rated)
2240
1949
 
@@ -2286,9 +1995,9 @@ class HVAC
2286
1995
  cop_ratios = [1.385171617, 1.183214059, 1.0, 0.95544453] # Updated based on Nordyne 3 ton heat pump
2287
1996
 
2288
1997
  # HSPF calculation is based on performance at three speeds
2289
- if calc_type.include? 'hspf'
1998
+ if calc_type == 'hspf'
2290
1999
  indices = [0, 1, 2]
2291
- else
2000
+ elsif calc_type == 'model'
2292
2001
  indices = [0, 1, 2, 3]
2293
2002
  end
2294
2003
 
@@ -2301,33 +2010,26 @@ class HVAC
2301
2010
  return cops_net
2302
2011
  end
2303
2012
 
2304
- def self.calc_biquad(coeff, in_1, in_2)
2305
- result = coeff[0] + coeff[1] * in_1 + coeff[2] * in_1 * in_1 + coeff[3] * in_2 + coeff[4] * in_2 * in_2 + coeff[5] * in_1 * in_2
2306
- return result
2307
- end
2308
-
2309
- def self.calc_eer_cooling_1speed(seer, fan_power_rated, coeff_eir)
2310
- # Directly calculate cooling coil net eer at condition A (95/80/67) using Seer
2013
+ def self.calc_eer_cooling_1speed(seer, c_d, fan_power_rated, coeff_eir)
2014
+ # Directly calculate cooling coil net EER at condition A (95/80/67) using SEER
2311
2015
 
2312
- c_d = get_cool_c_d(1, seer)
2313
-
2314
- # 1. Calculate eer_b using Seer and c_d
2016
+ # 1. Calculate EER_b using SEER and c_d
2315
2017
  eer_b = seer / (1.0 - 0.5 * c_d)
2316
2018
 
2317
- # 2. Calculate eir_b
2019
+ # 2. Calculate EIR_b
2318
2020
  eir_b = calc_eir_from_eer(eer_b, fan_power_rated)
2319
2021
 
2320
- # 3. Calculate eir_a using performance curves
2321
- eir_a = eir_b / calc_biquad(coeff_eir[0], 67.0, 82.0)
2022
+ # 3. Calculate EIR_a using performance curves
2023
+ eir_a = eir_b / MathTools.biquadratic(67.0, 82.0, coeff_eir[0])
2322
2024
  eer_a = calc_eer_from_eir(eir_a, fan_power_rated)
2323
2025
 
2324
2026
  return eer_a
2325
2027
  end
2326
2028
 
2327
- def self.calc_eers_cooling_2speed(runner, seer, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q, is_heat_pump = false)
2328
- # Iterate to find rated net eers given Seer using simple bisection method for two stage air conditioners
2029
+ def self.calc_eers_cooling_2speed(seer, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q)
2030
+ # Iterate to find rated net EERs given SEER using simple bisection method for two stage heat pumps
2329
2031
 
2330
- # Initial large bracket of eer (A condition) to span possible seer range
2032
+ # Initial large bracket of EER (A condition) to span possible SEER range
2331
2033
  eer_a = 5.0
2332
2034
  eer_b = 20.0
2333
2035
 
@@ -2338,10 +2040,10 @@ class HVAC
2338
2040
  err = 1
2339
2041
  eer_c = (eer_a + eer_b) / 2.0
2340
2042
  (1..iter_max).each do |n|
2341
- eers = calc_eers_from_eir_2speed(eer_a, fan_power_rated, is_heat_pump)
2043
+ eers = calc_eers_from_eir_2speed(eer_a, fan_power_rated)
2342
2044
  f_a = calc_seer_2speed(eers, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q) - seer
2343
2045
 
2344
- eers = calc_eers_from_eir_2speed(eer_c, fan_power_rated, is_heat_pump)
2046
+ eers = calc_eers_from_eir_2speed(eer_c, fan_power_rated)
2345
2047
  f_c = calc_seer_2speed(eers, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q) - seer
2346
2048
 
2347
2049
  if f_c == 0
@@ -2364,10 +2066,10 @@ class HVAC
2364
2066
  fail 'Two-speed cooling eers iteration failed to converge.'
2365
2067
  end
2366
2068
 
2367
- return calc_eers_from_eir_2speed(eer_c, fan_power_rated, is_heat_pump)
2069
+ return calc_eers_from_eir_2speed(eer_c, fan_power_rated)
2368
2070
  end
2369
2071
 
2370
- def self.calc_eers_cooling_4speed(runner, seer, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q)
2072
+ def self.calc_eers_cooling_4speed(seer, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q)
2371
2073
  # Iterate to find rated net eers given Seer using simple bisection method for two stage and variable speed air conditioners
2372
2074
 
2373
2075
  # Initial large bracket of eer (A condition) to span possible seer range
@@ -2412,17 +2114,17 @@ class HVAC
2412
2114
 
2413
2115
  def self.calc_seer_2speed(eers, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q)
2414
2116
  eir_A2 = calc_eir_from_eer(eers[1], fan_power_rated)
2415
- eir_B2 = eir_A2 * calc_biquad(coeff_eir[1], 67.0, 82.0)
2117
+ eir_B2 = eir_A2 * MathTools.biquadratic(67.0, 82.0, coeff_eir[1])
2416
2118
 
2417
2119
  eir_A1 = calc_eir_from_eer(eers[0], fan_power_rated)
2418
- eir_B1 = eir_A1 * calc_biquad(coeff_eir[0], 67.0, 82.0)
2419
- eir_F1 = eir_A1 * calc_biquad(coeff_eir[0], 67.0, 67.0)
2120
+ eir_B1 = eir_A1 * MathTools.biquadratic(67.0, 82.0, coeff_eir[0])
2121
+ eir_F1 = eir_A1 * MathTools.biquadratic(67.0, 67.0, coeff_eir[0])
2420
2122
 
2421
2123
  q_A2 = 1.0
2422
- q_B2 = q_A2 * calc_biquad(coeff_q[1], 67.0, 82.0)
2124
+ q_B2 = q_A2 * MathTools.biquadratic(67.0, 82.0, coeff_q[1])
2423
2125
 
2424
- q_B1 = q_A2 * capacity_ratios[0] * calc_biquad(coeff_q[0], 67.0, 82.0)
2425
- q_F1 = q_A2 * capacity_ratios[0] * calc_biquad(coeff_q[0], 67.0, 67.0)
2126
+ q_B1 = q_A2 * capacity_ratios[0] * MathTools.biquadratic(67.0, 82.0, coeff_q[0])
2127
+ q_F1 = q_A2 * capacity_ratios[0] * MathTools.biquadratic(67.0, 67.0, coeff_q[0])
2426
2128
 
2427
2129
  cfm_Btu_h = 400.0 / 12000.0
2428
2130
 
@@ -2479,20 +2181,20 @@ class HVAC
2479
2181
  tout_F = 67.0
2480
2182
 
2481
2183
  eir_A2 = calc_eir_from_eer(eers[n_max], fan_power_rated)
2482
- eir_B2 = eir_A2 * calc_biquad(coeff_eir[n_max], wBin, tout_B)
2184
+ eir_B2 = eir_A2 * MathTools.biquadratic(wBin, tout_B, coeff_eir[n_max])
2483
2185
 
2484
2186
  eir_Av = calc_eir_from_eer(eers[n_int], fan_power_rated)
2485
- eir_Ev = eir_Av * calc_biquad(coeff_eir[n_int], wBin, tout_E)
2187
+ eir_Ev = eir_Av * MathTools.biquadratic(wBin, tout_E, coeff_eir[n_int])
2486
2188
 
2487
2189
  eir_A1 = calc_eir_from_eer(eers[n_min], fan_power_rated)
2488
- eir_B1 = eir_A1 * calc_biquad(coeff_eir[n_min], wBin, tout_B)
2489
- eir_F1 = eir_A1 * calc_biquad(coeff_eir[n_min], wBin, tout_F)
2190
+ eir_B1 = eir_A1 * MathTools.biquadratic(wBin, tout_B, coeff_eir[n_min])
2191
+ eir_F1 = eir_A1 * MathTools.biquadratic(wBin, tout_F, coeff_eir[n_min])
2490
2192
 
2491
2193
  q_A2 = capacity_ratios[n_max]
2492
- q_B2 = q_A2 * calc_biquad(coeff_q[n_max], wBin, tout_B)
2493
- q_Ev = capacity_ratios[n_int] * calc_biquad(coeff_q[n_int], wBin, tout_E)
2494
- q_B1 = capacity_ratios[n_min] * calc_biquad(coeff_q[n_min], wBin, tout_B)
2495
- q_F1 = capacity_ratios[n_min] * calc_biquad(coeff_q[n_min], wBin, tout_F)
2194
+ q_B2 = q_A2 * MathTools.biquadratic(wBin, tout_B, coeff_q[n_max])
2195
+ q_Ev = capacity_ratios[n_int] * MathTools.biquadratic(wBin, tout_E, coeff_q[n_int])
2196
+ q_B1 = capacity_ratios[n_min] * MathTools.biquadratic(wBin, tout_B, coeff_q[n_min])
2197
+ q_F1 = capacity_ratios[n_min] * MathTools.biquadratic(wBin, tout_F, coeff_q[n_min])
2496
2198
 
2497
2199
  cfm_Btu_h = 400.0 / 12000.0
2498
2200
 
@@ -2659,7 +2361,7 @@ class HVAC
2659
2361
  return calc_cops_from_eir_2speed(cop_c, fan_power_rated)
2660
2362
  end
2661
2363
 
2662
- def self.calc_cops_heating_4speed(runner, hspf, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q)
2364
+ def self.calc_cops_heating_4speed(hspf, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q)
2663
2365
  # Iterate to find rated net cops given HSPF using simple bisection method for variable speed heat pumps
2664
2366
 
2665
2367
  # Initial large bracket of cop to span possible hspf range
@@ -2704,12 +2406,12 @@ class HVAC
2704
2406
 
2705
2407
  def self.calc_hspf_1speed(cop_47, c_d, fan_power_rated, coeff_eir, coeff_q)
2706
2408
  eir_47 = calc_eir_from_cop(cop_47, fan_power_rated)
2707
- eir_35 = eir_47 * calc_biquad(coeff_eir[0], 70.0, 35.0)
2708
- eir_17 = eir_47 * calc_biquad(coeff_eir[0], 70.0, 17.0)
2409
+ eir_35 = eir_47 * MathTools.biquadratic(70.0, 35.0, coeff_eir[0])
2410
+ eir_17 = eir_47 * MathTools.biquadratic(70.0, 17.0, coeff_eir[0])
2709
2411
 
2710
2412
  q_47 = 1.0
2711
2413
  q_35 = 0.7519
2712
- q_17 = q_47 * calc_biquad(coeff_q[0], 70.0, 17.0)
2414
+ q_17 = q_47 * MathTools.biquadratic(70.0, 17.0, coeff_q[0])
2713
2415
 
2714
2416
  cfm_Btu_h = 400.0 / 12000.0
2715
2417
 
@@ -2767,22 +2469,22 @@ class HVAC
2767
2469
 
2768
2470
  def self.calc_hspf_2speed(cops, c_d, capacity_ratios, fanspeed_ratios, fan_power_rated, coeff_eir, coeff_q)
2769
2471
  eir_47_H = calc_eir_from_cop(cops[1], fan_power_rated)
2770
- eir_35_H = eir_47_H * calc_biquad(coeff_eir[1], 70.0, 35.0)
2771
- eir_17_H = eir_47_H * calc_biquad(coeff_eir[1], 70.0, 17.0)
2472
+ eir_35_H = eir_47_H * MathTools.biquadratic(70.0, 35.0, coeff_eir[1])
2473
+ eir_17_H = eir_47_H * MathTools.biquadratic(70.0, 17.0, coeff_eir[1])
2772
2474
 
2773
2475
  eir_47_L = calc_eir_from_cop(cops[0], fan_power_rated)
2774
- eir_62_L = eir_47_L * calc_biquad(coeff_eir[0], 70.0, 62.0)
2775
- eir_35_L = eir_47_L * calc_biquad(coeff_eir[0], 70.0, 35.0)
2776
- eir_17_L = eir_47_L * calc_biquad(coeff_eir[0], 70.0, 17.0)
2476
+ eir_62_L = eir_47_L * MathTools.biquadratic(70.0, 62.0, coeff_eir[0])
2477
+ eir_35_L = eir_47_L * MathTools.biquadratic(70.0, 35.0, coeff_eir[0])
2478
+ eir_17_L = eir_47_L * MathTools.biquadratic(70.0, 17.0, coeff_eir[0])
2777
2479
 
2778
2480
  q_H47 = 1.0
2779
- q_H35 = q_H47 * calc_biquad(coeff_q[1], 70.0, 35.0)
2780
- q_H17 = q_H47 * calc_biquad(coeff_q[1], 70.0, 17.0)
2481
+ q_H35 = q_H47 * MathTools.biquadratic(70.0, 35.0, coeff_q[1])
2482
+ q_H17 = q_H47 * MathTools.biquadratic(70.0, 17.0, coeff_q[1])
2781
2483
 
2782
2484
  q_L47 = q_H47 * capacity_ratios[0]
2783
- q_L62 = q_L47 * calc_biquad(coeff_q[0], 70.0, 62.0)
2784
- q_L35 = q_L47 * calc_biquad(coeff_q[0], 70.0, 35.0)
2785
- q_L17 = q_L47 * calc_biquad(coeff_q[0], 70.0, 17.0)
2485
+ q_L62 = q_L47 * MathTools.biquadratic(70.0, 62.0, coeff_q[0])
2486
+ q_L35 = q_L47 * MathTools.biquadratic(70.0, 35.0, coeff_q[0])
2487
+ q_L17 = q_L47 * MathTools.biquadratic(70.0, 17.0, coeff_q[0])
2786
2488
 
2787
2489
  cfm_Btu_h = 400.0 / 12000.0
2788
2490
 
@@ -2887,21 +2589,21 @@ class HVAC
2887
2589
  tout_0 = 62.0
2888
2590
 
2889
2591
  eir_H1_2 = calc_eir_from_cop(cop_47[n_max], fan_power_rated)
2890
- eir_H3_2 = eir_H1_2 * calc_biquad(coeff_eir[n_max], tin, tout_3)
2592
+ eir_H3_2 = eir_H1_2 * MathTools.biquadratic(tin, tout_3, coeff_eir[n_max])
2891
2593
 
2892
2594
  eir_adjv = calc_eir_from_cop(cop_47[n_int], fan_power_rated)
2893
- eir_H2_v = eir_adjv * calc_biquad(coeff_eir[n_int], tin, tout_2)
2595
+ eir_H2_v = eir_adjv * MathTools.biquadratic(tin, tout_2, coeff_eir[n_int])
2894
2596
 
2895
2597
  eir_H1_1 = calc_eir_from_cop(cop_47[n_min], fan_power_rated)
2896
- eir_H0_1 = eir_H1_1 * calc_biquad(coeff_eir[n_min], tin, tout_0)
2598
+ eir_H0_1 = eir_H1_1 * MathTools.biquadratic(tin, tout_0, coeff_eir[n_min])
2897
2599
 
2898
2600
  q_H1_2 = capacity_ratios[n_max]
2899
- q_H3_2 = q_H1_2 * calc_biquad(coeff_q[n_max], tin, tout_3)
2601
+ q_H3_2 = q_H1_2 * MathTools.biquadratic(tin, tout_3, coeff_q[n_max])
2900
2602
 
2901
- q_H2_v = capacity_ratios[n_int] * calc_biquad(coeff_q[n_int], tin, tout_2)
2603
+ q_H2_v = capacity_ratios[n_int] * MathTools.biquadratic(tin, tout_2, coeff_q[n_int])
2902
2604
 
2903
2605
  q_H1_1 = capacity_ratios[n_min]
2904
- q_H0_1 = q_H1_1 * calc_biquad(coeff_q[n_min], tin, tout_0)
2606
+ q_H0_1 = q_H1_1 * MathTools.biquadratic(tin, tout_0, coeff_q[n_min])
2905
2607
 
2906
2608
  cfm_Btu_h = 400.0 / 12000.0
2907
2609
 
@@ -3004,29 +2706,46 @@ class HVAC
3004
2706
  return hspf
3005
2707
  end
3006
2708
 
3007
- def self.calc_cfms_ton_rated(rated_airflow_rate, fan_speed_ratios, capacity_ratios)
3008
- array = []
3009
- fan_speed_ratios.each_with_index do |fanspeed_ratio, i|
3010
- capacity_ratio = capacity_ratios[i]
3011
- array << fanspeed_ratio * rated_airflow_rate / capacity_ratio
2709
+ def self.set_cool_rated_cfm_per_ton(cooling_system)
2710
+ clg_ap = cooling_system.additional_properties
2711
+
2712
+ if cooling_system.is_a?(HPXML::CoolingSystem) && (cooling_system.cooling_system_type == HPXML::HVACTypeRoomAirConditioner)
2713
+ clg_ap.cool_rated_cfm_per_ton = [312.0] # medium speed
2714
+ else
2715
+ clg_ap.cool_rated_cfm_per_ton = []
2716
+ clg_ap.cool_fan_speed_ratios.each_with_index do |fanspeed_ratio, i|
2717
+ clg_ap.cool_rated_cfm_per_ton << fanspeed_ratio * clg_ap.cool_rated_airflow_rate / clg_ap.cool_capacity_ratios[i]
2718
+ end
2719
+ end
2720
+ end
2721
+
2722
+ def self.set_heat_rated_cfm_per_ton(heating_system)
2723
+ htg_ap = heating_system.additional_properties
2724
+
2725
+ if heating_system.is_a? HPXML::HeatingSystem
2726
+ htg_ap.heat_rated_cfm_per_ton = [350.0]
2727
+ else
2728
+ htg_ap.heat_rated_cfm_per_ton = []
2729
+ htg_ap.heat_fan_speed_ratios.each_with_index do |fanspeed_ratio, i|
2730
+ htg_ap.heat_rated_cfm_per_ton << fanspeed_ratio * htg_ap.heat_rated_airflow_rate / htg_ap.heat_capacity_ratios[i]
2731
+ end
3012
2732
  end
3013
- return array
3014
2733
  end
3015
2734
 
3016
2735
  def self.create_curve_biquadratic_constant(model)
3017
- const_biquadratic = OpenStudio::Model::CurveBiquadratic.new(model)
3018
- const_biquadratic.setName('ConstantBiquadratic')
3019
- const_biquadratic.setCoefficient1Constant(1)
3020
- const_biquadratic.setCoefficient2x(0)
3021
- const_biquadratic.setCoefficient3xPOW2(0)
3022
- const_biquadratic.setCoefficient4y(0)
3023
- const_biquadratic.setCoefficient5yPOW2(0)
3024
- const_biquadratic.setCoefficient6xTIMESY(0)
3025
- const_biquadratic.setMinimumValueofx(-100)
3026
- const_biquadratic.setMaximumValueofx(100)
3027
- const_biquadratic.setMinimumValueofy(-100)
3028
- const_biquadratic.setMaximumValueofy(100)
3029
- return const_biquadratic
2736
+ curve = OpenStudio::Model::CurveBiquadratic.new(model)
2737
+ curve.setName('ConstantBiquadratic')
2738
+ curve.setCoefficient1Constant(1)
2739
+ curve.setCoefficient2x(0)
2740
+ curve.setCoefficient3xPOW2(0)
2741
+ curve.setCoefficient4y(0)
2742
+ curve.setCoefficient5yPOW2(0)
2743
+ curve.setCoefficient6xTIMESY(0)
2744
+ curve.setMinimumValueofx(-100)
2745
+ curve.setMaximumValueofx(100)
2746
+ curve.setMinimumValueofy(-100)
2747
+ curve.setMaximumValueofy(100)
2748
+ return curve
3030
2749
  end
3031
2750
 
3032
2751
  def self.create_curve_quadratic_constant(model)
@@ -3043,15 +2762,15 @@ class HVAC
3043
2762
  end
3044
2763
 
3045
2764
  def self.create_curve_cubic_constant(model)
3046
- constant_cubic = OpenStudio::Model::CurveCubic.new(model)
3047
- constant_cubic.setName('ConstantCubic')
3048
- constant_cubic.setCoefficient1Constant(1)
3049
- constant_cubic.setCoefficient2x(0)
3050
- constant_cubic.setCoefficient3xPOW2(0)
3051
- constant_cubic.setCoefficient4xPOW3(0)
3052
- constant_cubic.setMinimumValueofx(-100)
3053
- constant_cubic.setMaximumValueofx(100)
3054
- return constant_cubic
2765
+ curve = OpenStudio::Model::CurveCubic.new(model)
2766
+ curve.setName('ConstantCubic')
2767
+ curve.setCoefficient1Constant(1)
2768
+ curve.setCoefficient2x(0)
2769
+ curve.setCoefficient3xPOW2(0)
2770
+ curve.setCoefficient4xPOW3(0)
2771
+ curve.setMinimumValueofx(-100)
2772
+ curve.setMaximumValueofx(100)
2773
+ return curve
3055
2774
  end
3056
2775
 
3057
2776
  def self.convert_curve_biquadratic(coeff, ip_to_si = true)
@@ -3078,29 +2797,6 @@ class HVAC
3078
2797
  end
3079
2798
  end
3080
2799
 
3081
- def self.convert_curve_gshp(coeff, gshp_to_biquadratic)
3082
- m1 = 32 - 273.15 * 1.8
3083
- m2 = 283 * 1.8
3084
- if gshp_to_biquadratic
3085
- biq_coeff = []
3086
- biq_coeff << coeff[0] - m1 * ((coeff[1] + coeff[2]) / m2)
3087
- biq_coeff << coeff[1] / m2
3088
- biq_coeff << 0
3089
- biq_coeff << coeff[2] / m2
3090
- biq_coeff << 0
3091
- biq_coeff << 0
3092
- return biq_coeff
3093
- else
3094
- gsph_coeff = []
3095
- gsph_coeff << coeff[0] + m1 * (coeff[1] + coeff[3])
3096
- gsph_coeff << m2 * coeff[1]
3097
- gsph_coeff << m2 * coeff[3]
3098
- gsph_coeff << 0
3099
- gsph_coeff << 0
3100
- return gsph_coeff
3101
- end
3102
- end
3103
-
3104
2800
  def self.create_curve_biquadratic(model, coeff, name, min_x, max_x, min_y, max_y)
3105
2801
  curve = OpenStudio::Model::CurveBiquadratic.new(model)
3106
2802
  curve.setName(name)
@@ -3183,40 +2879,67 @@ class HVAC
3183
2879
  return curve
3184
2880
  end
3185
2881
 
3186
- def self.create_dx_cooling_coil(model, obj_name, speed_indices, eirs, cap_ft_spec, eir_ft_spec, closs_fplr_spec, cap_fflow_spec, eir_fflow_spec, shrs_rated_gross, capacity, crankcase_kw, crankcase_temp, fan_power_rated)
3187
- num_speeds = speed_indices.size
2882
+ def self.create_curve_quad_linear(model, coeff, name)
2883
+ curve = OpenStudio::Model::CurveQuadLinear.new(model)
2884
+ curve.setName(name)
2885
+ curve.setCoefficient1Constant(coeff[0])
2886
+ curve.setCoefficient2w(coeff[1])
2887
+ curve.setCoefficient3x(coeff[2])
2888
+ curve.setCoefficient4y(coeff[3])
2889
+ curve.setCoefficient5z(coeff[4])
2890
+ return curve
2891
+ end
3188
2892
 
3189
- if num_speeds > 1
2893
+ def self.create_curve_quint_linear(model, coeff, name)
2894
+ curve = OpenStudio::Model::CurveQuintLinear.new(model)
2895
+ curve.setName(name)
2896
+ curve.setCoefficient1Constant(coeff[0])
2897
+ curve.setCoefficient2v(coeff[1])
2898
+ curve.setCoefficient3w(coeff[2])
2899
+ curve.setCoefficient4x(coeff[3])
2900
+ curve.setCoefficient5y(coeff[4])
2901
+ curve.setCoefficient6z(coeff[5])
2902
+ return curve
2903
+ end
2904
+
2905
+ def self.create_dx_cooling_coil(model, obj_name, cooling_system)
2906
+ clg_ap = cooling_system.additional_properties
2907
+
2908
+ if cooling_system.is_a? HPXML::CoolingSystem
2909
+ clg_type = cooling_system.cooling_system_type
2910
+ elsif cooling_system.is_a? HPXML::HeatPump
2911
+ clg_type = cooling_system.heat_pump_type
2912
+ end
2913
+
2914
+ if clg_ap.num_speeds > 1
3190
2915
  constant_biquadratic = create_curve_biquadratic_constant(model)
3191
2916
  end
3192
2917
 
3193
2918
  clg_coil = nil
3194
2919
 
3195
- for speed_idx in speed_indices
3196
- speed = speed_idx + 1
3197
- cap_ft_spec_si = convert_curve_biquadratic(cap_ft_spec[speed_idx])
3198
- eir_ft_spec_si = convert_curve_biquadratic(eir_ft_spec[speed_idx])
3199
- cap_ft_curve = create_curve_biquadratic(model, cap_ft_spec_si, "Cool-Cap-fT#{speed}", 13.88, 23.88, 18.33, 51.66)
3200
- eir_ft_curve = create_curve_biquadratic(model, eir_ft_spec_si, "Cool-eir-fT#{speed}", 13.88, 23.88, 18.33, 51.66)
3201
- plf_fplr_curve = create_curve_quadratic(model, closs_fplr_spec[speed_idx], "Cool-PLF-fPLR#{speed}", 0, 1, 0.7, 1)
3202
- cap_fff_curve = create_curve_quadratic(model, cap_fflow_spec[speed_idx], "Cool-Cap-fFF#{speed}", 0, 2, 0, 2)
3203
- eir_fff_curve = create_curve_quadratic(model, eir_fflow_spec[speed_idx], "Cool-eir-fFF#{speed}", 0, 2, 0, 2)
3204
-
3205
- if num_speeds == 1
2920
+ for i in 0..(clg_ap.num_speeds - 1)
2921
+ cap_ft_spec_si = convert_curve_biquadratic(clg_ap.cool_cap_ft_spec[i])
2922
+ eir_ft_spec_si = convert_curve_biquadratic(clg_ap.cool_eir_ft_spec[i])
2923
+ cap_ft_curve = create_curve_biquadratic(model, cap_ft_spec_si, "Cool-CAP-fT#{i + 1}", 13.88, 23.88, 18.33, 51.66)
2924
+ eir_ft_curve = create_curve_biquadratic(model, eir_ft_spec_si, "Cool-EIR-fT#{i + 1}", 13.88, 23.88, 18.33, 51.66)
2925
+ plf_fplr_curve = create_curve_quadratic(model, clg_ap.cool_plf_fplr_spec[i], "Cool-PLF-fPLR#{i + 1}", 0, 1, 0.7, 1)
2926
+ cap_fff_curve = create_curve_quadratic(model, clg_ap.cool_cap_fflow_spec[i], "Cool-CAP-fFF#{i + 1}", 0, 2, 0, 2)
2927
+ eir_fff_curve = create_curve_quadratic(model, clg_ap.cool_eir_fflow_spec[i], "Cool-EIR-fFF#{i + 1}", 0, 2, 0, 2)
2928
+
2929
+ if clg_ap.num_speeds == 1
3206
2930
  clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model, model.alwaysOnDiscreteSchedule, cap_ft_curve, cap_fff_curve, eir_ft_curve, eir_fff_curve, plf_fplr_curve)
3207
- clg_coil.setRatedEvaporatorFanPowerPerVolumeFlowRate(fan_power_rated / UnitConversions.convert(1.0, 'cfm', 'm^3/s'))
3208
- if not crankcase_temp.nil?
3209
- clg_coil.setMaximumOutdoorDryBulbTemperatureForCrankcaseHeaterOperation(UnitConversions.convert(crankcase_temp, 'F', 'C'))
3210
- end
3211
- clg_coil.setRatedCOP(1.0 / eirs[speed_idx])
3212
- clg_coil.setRatedSensibleHeatRatio(shrs_rated_gross[speed_idx])
3213
- if not capacity.nil?
3214
- clg_coil.setRatedTotalCoolingCapacity(UnitConversions.convert([capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
2931
+ clg_coil.setRatedEvaporatorFanPowerPerVolumeFlowRate(clg_ap.fan_power_rated / UnitConversions.convert(1.0, 'cfm', 'm^3/s'))
2932
+ if not clg_ap.crankcase_temp.nil?
2933
+ clg_coil.setMaximumOutdoorDryBulbTemperatureForCrankcaseHeaterOperation(UnitConversions.convert(clg_ap.crankcase_temp, 'F', 'C'))
3215
2934
  end
2935
+ clg_coil.setRatedCOP(1.0 / clg_ap.cool_rated_eirs[i])
2936
+ clg_coil.setRatedSensibleHeatRatio(clg_ap.cool_rated_shrs_gross[i])
3216
2937
  clg_coil.setNominalTimeForCondensateRemovalToBegin(1000.0)
3217
2938
  clg_coil.setRatioOfInitialMoistureEvaporationRateAndSteadyStateLatentCapacity(1.5)
3218
2939
  clg_coil.setMaximumCyclingRate(3.0)
3219
2940
  clg_coil.setLatentCapacityTimeConstant(45.0)
2941
+ clg_coil.setRatedTotalCoolingCapacity(UnitConversions.convert(cooling_system.cooling_capacity, 'Btu/hr', 'W'))
2942
+ clg_coil.setRatedAirFlowRate(calc_rated_airflow(cooling_system.cooling_capacity, clg_ap.cool_rated_cfm_per_ton[0], 1.0))
3220
2943
  else
3221
2944
  if clg_coil.nil?
3222
2945
  clg_coil = OpenStudio::Model::CoilCoolingDXMultiSpeed.new(model)
@@ -3224,331 +2947,225 @@ class HVAC
3224
2947
  clg_coil.setApplyLatentDegradationtoSpeedsGreaterthan1(false)
3225
2948
  clg_coil.setFuelType(EPlus::FuelTypeElectricity)
3226
2949
  clg_coil.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
3227
- if not crankcase_temp.nil?
3228
- clg_coil.setMaximumOutdoorDryBulbTemperatureforCrankcaseHeaterOperation(UnitConversions.convert(crankcase_temp, 'F', 'C'))
2950
+ if not clg_ap.crankcase_temp.nil?
2951
+ clg_coil.setMaximumOutdoorDryBulbTemperatureforCrankcaseHeaterOperation(UnitConversions.convert(clg_ap.crankcase_temp, 'F', 'C'))
3229
2952
  end
3230
2953
  end
3231
2954
  stage = OpenStudio::Model::CoilCoolingDXMultiSpeedStageData.new(model, cap_ft_curve, cap_fff_curve, eir_ft_curve, eir_fff_curve, plf_fplr_curve, constant_biquadratic)
3232
- stage.setGrossRatedCoolingCOP(1.0 / eirs[speed_idx])
3233
- stage.setGrossRatedSensibleHeatRatio(shrs_rated_gross[speed_idx])
3234
- if not capacity.nil?
3235
- stage.setGrossRatedTotalCoolingCapacity(UnitConversions.convert([capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
3236
- end
2955
+ stage.setGrossRatedCoolingCOP(1.0 / clg_ap.cool_rated_eirs[i])
2956
+ stage.setGrossRatedSensibleHeatRatio(clg_ap.cool_rated_shrs_gross[i])
3237
2957
  stage.setNominalTimeforCondensateRemovaltoBegin(1000)
3238
2958
  stage.setRatioofInitialMoistureEvaporationRateandSteadyStateLatentCapacity(1.5)
3239
2959
  stage.setRatedWasteHeatFractionofPowerInput(0.2)
3240
2960
  stage.setMaximumCyclingRate(3.0)
3241
2961
  stage.setLatentCapacityTimeConstant(45.0)
2962
+ stage.setGrossRatedTotalCoolingCapacity(UnitConversions.convert(cooling_system.cooling_capacity, 'Btu/hr', 'W') * clg_ap.cool_capacity_ratios[i])
2963
+ stage.setRatedAirFlowRate(calc_rated_airflow(cooling_system.cooling_capacity, clg_ap.cool_rated_cfm_per_ton[i], clg_ap.cool_capacity_ratios[i]))
3242
2964
  clg_coil.addStage(stage)
3243
2965
  end
3244
2966
  end
3245
2967
 
3246
2968
  clg_coil.setName(obj_name + ' clg coil')
3247
2969
  clg_coil.setCondenserType('AirCooled')
3248
- clg_coil.setCrankcaseHeaterCapacity(UnitConversions.convert(crankcase_kw, 'kW', 'W'))
2970
+ clg_coil.setCrankcaseHeaterCapacity(UnitConversions.convert(clg_ap.crankcase_kw, 'kW', 'W'))
3249
2971
 
3250
2972
  return clg_coil
3251
2973
  end
3252
2974
 
3253
- def self.create_dx_heating_coil(model, obj_name, speed_indices, eirs, cap_ft_spec, eir_ft_spec, closs_fplr_spec, cap_fflow_spec, eir_fflow_spec,
3254
- capacity, crankcase_kw, crankcase_temp, fan_power_rated, hp_min_temp, fraction_heat_load_served)
3255
- num_speeds = speed_indices.size
2975
+ def self.create_dx_heating_coil(model, obj_name, heating_system)
2976
+ htg_ap = heating_system.additional_properties
3256
2977
 
3257
- if num_speeds > 1
2978
+ if heating_system.is_a? HPXML::HeatingSystem
2979
+ htg_type = heating_system.heating_system_type
2980
+ elsif heating_system.is_a? HPXML::HeatPump
2981
+ htg_type = heating_system.heat_pump_type
2982
+ end
2983
+
2984
+ if htg_ap.num_speeds > 1
3258
2985
  constant_biquadratic = create_curve_biquadratic_constant(model)
3259
2986
  end
3260
2987
 
3261
2988
  htg_coil = nil
3262
2989
 
3263
- for speed_idx in speed_indices
3264
- speed = speed_idx + 1
3265
- cap_ft_spec_si = convert_curve_biquadratic(cap_ft_spec[speed_idx])
3266
- eir_ft_spec_si = convert_curve_biquadratic(eir_ft_spec[speed_idx])
3267
- cap_ft_curve = create_curve_biquadratic(model, cap_ft_spec_si, "HP_Heat-Cap-fT#{speed}", -100, 100, -100, 100)
3268
- eir_ft_curve = create_curve_biquadratic(model, eir_ft_spec_si, "HP_Heat-eir-fT#{speed}", -100, 100, -100, 100)
3269
- plf_fplr_curve = create_curve_quadratic(model, closs_fplr_spec[speed_idx], "HP_Heat-PLF-fPLR#{speed}", 0, 1, 0.7, 1)
3270
- cap_fff_curve = create_curve_quadratic(model, cap_fflow_spec[speed_idx], "HP_Heat-CAP-fFF#{speed}", 0, 2, 0, 2)
3271
- eir_fff_curve = create_curve_quadratic(model, eir_fflow_spec[speed_idx], "HP_Heat-eir-fFF#{speed}", 0, 2, 0, 2)
3272
-
3273
- if num_speeds == 1
2990
+ for i in 0..(htg_ap.num_speeds - 1)
2991
+ cap_ft_spec_si = convert_curve_biquadratic(htg_ap.heat_cap_ft_spec[i])
2992
+ eir_ft_spec_si = convert_curve_biquadratic(htg_ap.heat_eir_ft_spec[i])
2993
+ cap_ft_curve = create_curve_biquadratic(model, cap_ft_spec_si, "Heat-CAP-fT#{i + 1}", -100, 100, -100, 100)
2994
+ eir_ft_curve = create_curve_biquadratic(model, eir_ft_spec_si, "Heat-EIR-fT#{i + 1}", -100, 100, -100, 100)
2995
+ plf_fplr_curve = create_curve_quadratic(model, htg_ap.heat_plf_fplr_spec[i], "Heat-PLF-fPLR#{i + 1}", 0, 1, 0.7, 1)
2996
+ cap_fff_curve = create_curve_quadratic(model, htg_ap.heat_cap_fflow_spec[i], "Heat-CAP-fFF#{i + 1}", 0, 2, 0, 2)
2997
+ eir_fff_curve = create_curve_quadratic(model, htg_ap.heat_eir_fflow_spec[i], "Heat-EIR-fFF#{i + 1}", 0, 2, 0, 2)
2998
+
2999
+ if htg_ap.num_speeds == 1
3274
3000
  htg_coil = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(model, model.alwaysOnDiscreteSchedule, cap_ft_curve, cap_fff_curve, eir_ft_curve, eir_fff_curve, plf_fplr_curve)
3275
- htg_coil.setRatedSupplyFanPowerPerVolumeFlowRate(fan_power_rated / UnitConversions.convert(1.0, 'cfm', 'm^3/s'))
3276
- htg_coil.setRatedCOP(1.0 / eirs[speed_idx])
3277
- if not capacity.nil?
3278
- htg_coil.setRatedTotalHeatingCapacity(UnitConversions.convert([capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
3279
- end
3280
- if not crankcase_temp.nil?
3281
- htg_coil.setMaximumOutdoorDryBulbTemperatureforCrankcaseHeaterOperation(UnitConversions.convert(crankcase_temp, 'F', 'C'))
3001
+ htg_coil.setRatedSupplyFanPowerPerVolumeFlowRate(htg_ap.fan_power_rated / UnitConversions.convert(1.0, 'cfm', 'm^3/s'))
3002
+ htg_coil.setRatedCOP(1.0 / htg_ap.heat_rated_eirs[i])
3003
+ if not htg_ap.crankcase_temp.nil?
3004
+ htg_coil.setMaximumOutdoorDryBulbTemperatureforCrankcaseHeaterOperation(UnitConversions.convert(htg_ap.crankcase_temp, 'F', 'C'))
3282
3005
  end
3006
+ htg_coil.setRatedTotalHeatingCapacity(UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W'))
3007
+ htg_coil.setRatedAirFlowRate(calc_rated_airflow(heating_system.heating_capacity, htg_ap.heat_rated_cfm_per_ton[0], 1.0))
3283
3008
  else
3284
3009
  if htg_coil.nil?
3285
3010
  htg_coil = OpenStudio::Model::CoilHeatingDXMultiSpeed.new(model)
3286
3011
  htg_coil.setFuelType(EPlus::FuelTypeElectricity)
3287
3012
  htg_coil.setApplyPartLoadFractiontoSpeedsGreaterthan1(false)
3288
3013
  htg_coil.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
3289
- if not crankcase_temp.nil?
3290
- htg_coil.setMaximumOutdoorDryBulbTemperatureforCrankcaseHeaterOperation(UnitConversions.convert(crankcase_temp, 'F', 'C'))
3014
+ if not htg_ap.crankcase_temp.nil?
3015
+ htg_coil.setMaximumOutdoorDryBulbTemperatureforCrankcaseHeaterOperation(UnitConversions.convert(htg_ap.crankcase_temp, 'F', 'C'))
3291
3016
  end
3292
3017
  end
3293
3018
  stage = OpenStudio::Model::CoilHeatingDXMultiSpeedStageData.new(model, cap_ft_curve, cap_fff_curve, eir_ft_curve, eir_fff_curve, plf_fplr_curve, constant_biquadratic)
3294
- stage.setGrossRatedHeatingCOP(1.0 / eirs[speed_idx])
3295
- if not capacity.nil?
3296
- stage.setGrossRatedHeatingCapacity(UnitConversions.convert([capacity, Constants.small].max, 'Btu/hr', 'W')) # Used by HVACSizing measure
3297
- end
3019
+ stage.setGrossRatedHeatingCOP(1.0 / htg_ap.heat_rated_eirs[i])
3298
3020
  stage.setRatedWasteHeatFractionofPowerInput(0.2)
3021
+ stage.setGrossRatedHeatingCapacity(UnitConversions.convert(heating_system.heating_capacity, 'Btu/hr', 'W') * htg_ap.heat_capacity_ratios[i])
3022
+ stage.setRatedAirFlowRate(calc_rated_airflow(heating_system.heating_capacity, htg_ap.heat_rated_cfm_per_ton[i], htg_ap.heat_capacity_ratios[i]))
3299
3023
  htg_coil.addStage(stage)
3300
3024
  end
3301
3025
  end
3302
3026
 
3303
3027
  htg_coil.setName(obj_name + ' htg coil')
3304
- htg_coil.setMinimumOutdoorDryBulbTemperatureforCompressorOperation(UnitConversions.convert(hp_min_temp, 'F', 'C'))
3028
+ htg_coil.setMinimumOutdoorDryBulbTemperatureforCompressorOperation(UnitConversions.convert(htg_ap.hp_min_temp, 'F', 'C'))
3305
3029
  htg_coil.setMaximumOutdoorDryBulbTemperatureforDefrostOperation(UnitConversions.convert(40.0, 'F', 'C'))
3306
- if fraction_heat_load_served > 0
3307
- defrost_eir_curve = create_curve_biquadratic(model, [0.1528, 0, 0, 0, 0, 0], 'Defrosteir', -100, 100, -100, 100) # Heating defrost curve for reverse cycle
3308
- htg_coil.setDefrostEnergyInputRatioFunctionofTemperatureCurve(defrost_eir_curve)
3309
- htg_coil.setDefrostStrategy('ReverseCycle')
3310
- htg_coil.setDefrostControl('Timed')
3311
- else
3312
- htg_coil.setDefrostTimePeriodFraction(0)
3030
+ defrost_eir_curve = create_curve_biquadratic(model, [0.1528, 0, 0, 0, 0, 0], 'Defrosteir', -100, 100, -100, 100) # Heating defrost curve for reverse cycle
3031
+ htg_coil.setDefrostEnergyInputRatioFunctionofTemperatureCurve(defrost_eir_curve)
3032
+ htg_coil.setDefrostStrategy('ReverseCycle')
3033
+ htg_coil.setDefrostControl('Timed')
3034
+ if heating_system.fraction_heat_load_served == 0
3035
+ htg_coil.setResistiveDefrostHeaterCapacity(0)
3313
3036
  end
3314
- htg_coil.setCrankcaseHeaterCapacity(UnitConversions.convert(crankcase_kw, 'kW', 'W'))
3037
+ htg_coil.setCrankcaseHeaterCapacity(UnitConversions.convert(htg_ap.crankcase_kw, 'kW', 'W'))
3315
3038
 
3316
3039
  return htg_coil
3317
3040
  end
3318
3041
 
3319
- def self.calc_cool_eirs(num_speeds, eers, fan_power_rated)
3320
- cool_eirs = []
3321
- (0...num_speeds).to_a.each do |speed|
3322
- eir = calc_eir_from_eer(eers[speed], fan_power_rated)
3323
- cool_eirs << eir
3042
+ def self.set_cool_rated_eirs(cooling_system)
3043
+ clg_ap = cooling_system.additional_properties
3044
+
3045
+ clg_ap.cool_rated_eirs = []
3046
+ (0...clg_ap.num_speeds).to_a.each do |speed|
3047
+ clg_ap.cool_rated_eirs << calc_eir_from_eer(clg_ap.cool_eers[speed], clg_ap.fan_power_rated)
3324
3048
  end
3325
- return cool_eirs
3326
3049
  end
3327
3050
 
3328
- def self.calc_heat_eirs(num_speeds, cops, fan_power_rated)
3329
- heat_eirs = []
3330
- (0...num_speeds).to_a.each do |speed|
3331
- eir = calc_eir_from_cop(cops[speed], fan_power_rated)
3332
- heat_eirs << eir
3051
+ def self.set_heat_rated_eirs(heating_system)
3052
+ htg_ap = heating_system.additional_properties
3053
+
3054
+ htg_ap.heat_rated_eirs = []
3055
+ (0...htg_ap.num_speeds).to_a.each do |speed|
3056
+ htg_ap.heat_rated_eirs << calc_eir_from_cop(htg_ap.heat_cops[speed], htg_ap.fan_power_rated)
3333
3057
  end
3334
- return heat_eirs
3335
3058
  end
3336
3059
 
3337
- def self.calc_shrs_rated_gross(num_speeds, shr_Rated_Net, fan_power_rated, cfms_ton_rated)
3338
- # Convert SHRs from net to gross
3339
- cool_shrs_rated_gross = []
3340
- (0...num_speeds).to_a.each do |speed|
3341
- qtot_net_nominal = 12000.0
3342
- qsens_net_nominal = qtot_net_nominal * shr_Rated_Net[speed]
3343
- qtot_gross_nominal = qtot_net_nominal + UnitConversions.convert(cfms_ton_rated[speed] * fan_power_rated, 'Wh', 'Btu')
3344
- qsens_gross_nominal = qsens_net_nominal + UnitConversions.convert(cfms_ton_rated[speed] * fan_power_rated, 'Wh', 'Btu')
3345
- cool_shrs_rated_gross << (qsens_gross_nominal / qtot_gross_nominal)
3346
-
3347
- # Make sure SHR's are in valid range based on E+ model limits.
3348
- # The following correlation was developed by Jon Winkler to test for maximum allowed SHR based on the 300 - 450 cfm/ton limits in E+
3349
- maxSHR = 0.3821066 + 0.001050652 * cfms_ton_rated[speed] - 0.01
3350
- cool_shrs_rated_gross[speed] = [cool_shrs_rated_gross[speed], maxSHR].min
3351
- minSHR = 0.60 # Approximate minimum SHR such that an ADP exists
3352
- cool_shrs_rated_gross[speed] = [cool_shrs_rated_gross[speed], minSHR].max
3353
- end
3354
-
3355
- return cool_shrs_rated_gross
3060
+ def self.set_cool_rated_shrs_gross(cooling_system)
3061
+ clg_ap = cooling_system.additional_properties
3062
+
3063
+ # Convert SHRs from net to gross.
3064
+ if cooling_system.is_a?(HPXML::CoolingSystem) && (cooling_system.cooling_system_type == HPXML::HVACTypeRoomAirConditioner)
3065
+ clg_ap.cool_rated_shrs_gross = [cooling_system.cooling_shr] # We don't model the fan separately, so set gross == net
3066
+ else
3067
+ clg_ap.cool_rated_shrs_gross = []
3068
+ (0...clg_ap.num_speeds).to_a.each do |speed|
3069
+ qtot_net_nominal = 12000.0
3070
+ qsens_net_nominal = qtot_net_nominal * clg_ap.cool_rated_shrs_net[speed]
3071
+ qtot_gross_nominal = qtot_net_nominal + UnitConversions.convert(clg_ap.cool_rated_cfm_per_ton[speed] * clg_ap.fan_power_rated, 'Wh', 'Btu')
3072
+ qsens_gross_nominal = qsens_net_nominal + UnitConversions.convert(clg_ap.cool_rated_cfm_per_ton[speed] * clg_ap.fan_power_rated, 'Wh', 'Btu')
3073
+ clg_ap.cool_rated_shrs_gross << (qsens_gross_nominal / qtot_gross_nominal)
3074
+
3075
+ # Make sure SHR's are in valid range based on E+ model limits.
3076
+ # The following correlation was developed by Jon Winkler to test for maximum allowed SHR based on the 300 - 450 cfm/ton limits in E+
3077
+ max_shr = 0.3821066 + 0.001050652 * clg_ap.cool_rated_cfm_per_ton[speed] - 0.01
3078
+ clg_ap.cool_rated_shrs_gross[speed] = [clg_ap.cool_rated_shrs_gross[speed], max_shr].min
3079
+ min_shr = 0.60 # Approximate minimum SHR such that an ADP exists
3080
+ clg_ap.cool_rated_shrs_gross[speed] = [clg_ap.cool_rated_shrs_gross[speed], min_shr].max
3081
+ end
3082
+ end
3356
3083
  end
3357
3084
 
3358
3085
  def self.calc_plr_coefficients(c_d)
3359
3086
  return [(1.0 - c_d), c_d, 0.0] # Linear part load model
3360
3087
  end
3361
3088
 
3362
- def self.get_cool_c_d(num_speeds, seer)
3089
+ def self.set_cool_c_d(cooling_system, num_speeds)
3090
+ clg_ap = cooling_system.additional_properties
3091
+
3363
3092
  # Degradation coefficient for cooling
3364
- if num_speeds == 1
3365
- if seer < 13.0
3366
- return 0.20
3093
+ if cooling_system.is_a?(HPXML::CoolingSystem) && (cooling_system.cooling_system_type == HPXML::HVACTypeRoomAirConditioner)
3094
+ clg_ap.cool_c_d = 0.22
3095
+ elsif num_speeds == 1
3096
+ if cooling_system.cooling_efficiency_seer < 13.0
3097
+ clg_ap.cool_c_d = 0.20
3367
3098
  else
3368
- return 0.07
3099
+ clg_ap.cool_c_d = 0.07
3369
3100
  end
3370
3101
  elsif num_speeds == 2
3371
- return 0.11
3372
- elsif num_speeds == 4
3373
- return 0.25
3374
- elsif num_speeds == 10
3375
- return 0.25
3102
+ clg_ap.cool_c_d = 0.11
3103
+ elsif num_speeds >= 4
3104
+ clg_ap.cool_c_d = 0.25
3376
3105
  end
3106
+
3107
+ # PLF curve
3108
+ clg_ap.cool_plf_fplr_spec = [calc_plr_coefficients(clg_ap.cool_c_d)] * num_speeds
3377
3109
  end
3378
3110
 
3379
- def self.get_heat_c_d(num_speeds, hspf)
3111
+ def self.set_heat_c_d(heating_system, num_speeds)
3112
+ htg_ap = heating_system.additional_properties
3113
+
3380
3114
  # Degradation coefficient for heating
3381
3115
  if num_speeds == 1
3382
- if hspf < 7.0
3383
- return 0.20
3116
+ if heating_system.heating_efficiency_hspf < 7.0
3117
+ htg_ap.heat_c_d = 0.20
3384
3118
  else
3385
- return 0.11
3119
+ htg_ap.heat_c_d = 0.11
3386
3120
  end
3387
3121
  elsif num_speeds == 2
3388
- return 0.11
3122
+ htg_ap.heat_c_d = 0.11
3389
3123
  elsif num_speeds == 4
3390
- return 0.24
3391
- elsif num_speeds == 10
3392
- return 0.40
3124
+ htg_ap.heat_c_d = 0.24
3125
+ elsif num_speeds == 10 # mini-split heat pump
3126
+ htg_ap.heat_c_d = 0.40
3393
3127
  end
3128
+
3129
+ htg_ap.heat_plf_fplr_spec = [calc_plr_coefficients(htg_ap.heat_c_d)] * num_speeds
3394
3130
  end
3395
3131
 
3396
- def self.get_fan_power_rated(seer)
3397
- if seer <= 15
3398
- return 0.365 # W/cfm
3132
+ def self.set_fan_power_rated(hvac_system)
3133
+ hvac_ap = hvac_system.additional_properties
3134
+
3135
+ if (hvac_system.is_a?(HPXML::CoolingSystem) && (hvac_system.cooling_system_type == HPXML::HVACTypeMiniSplitAirConditioner)) ||
3136
+ (hvac_system.is_a?(HPXML::HeatPump) && (hvac_system.heat_pump_type == HPXML::HVACTypeHeatPumpMiniSplit))
3137
+ if not hvac_system.distribution_system.nil?
3138
+ # Ducted, installed fan power may differ from rated fan power
3139
+ hvac_ap.fan_power_rated = 0.18 # W/cfm, ducted
3140
+ else
3141
+ # Ductless, installed and rated value should be equal
3142
+ hvac_ap.fan_power_rated = 0.07 # W/cfm
3143
+ hvac_system.fan_watts_per_cfm = hvac_ap.fan_power_rated # W/cfm
3144
+ end
3145
+ elsif hvac_system.cooling_efficiency_seer <= 15
3146
+ hvac_ap.fan_power_rated = 0.365 # W/cfm
3399
3147
  else
3400
- return 0.14 # W/cfm
3148
+ hvac_ap.fan_power_rated = 0.14 # W/cfm
3401
3149
  end
3402
3150
  end
3403
3151
 
3404
- def self.get_fan_power_installed(seer)
3405
- if seer <= 15
3406
- return 0.365 # W/cfm
3152
+ def self.set_fan_power(fan, fan_watts_per_cfm)
3153
+ if fan_watts_per_cfm > 0
3154
+ fan_eff = 0.75 # Overall Efficiency of the Fan, Motor and Drive
3155
+ fan.setFanEfficiency(fan_eff)
3156
+ fan.setPressureRise(fan_eff * fan_watts_per_cfm / UnitConversions.convert(1.0, 'cfm', 'm^3/s')) # Pa
3407
3157
  else
3408
- return 0.14 # W/cfm
3158
+ fan.setFanEfficiency(1)
3159
+ fan.setPressureRise(0)
3409
3160
  end
3410
3161
  end
3411
3162
 
3412
- def self.calc_fan_pressure_rise(fan_eff, fan_power)
3413
- # Calculates needed fan pressure rise to achieve a given fan power with an assumed efficiency.
3414
- # Previously we calculated the fan efficiency from an assumed pressure rise, which could lead to
3415
- # errors (fan efficiencies > 1).
3416
- return fan_eff * fan_power / UnitConversions.convert(1.0, 'cfm', 'm^3/s') # Pa
3417
- end
3418
-
3419
3163
  def self.calc_pump_rated_flow_rate(pump_eff, pump_w, pump_head_pa)
3420
3164
  # Calculate needed pump rated flow rate to achieve a given pump power with an assumed
3421
3165
  # efficiency and pump head.
3422
3166
  return pump_eff * pump_w / pump_head_pa # m3/s
3423
3167
  end
3424
3168
 
3425
- def self.existing_equipment(model, thermal_zone, runner)
3426
- # Returns a list of equipment objects
3427
-
3428
- equipment = []
3429
- hvac_types = []
3430
-
3431
- unitary_system_air_loops = get_unitary_system_air_loops(model, thermal_zone)
3432
- unitary_system_air_loops.each do |unitary_system_air_loop|
3433
- system, clg_coil, htg_coil, air_loop = unitary_system_air_loop
3434
- equipment << system
3435
-
3436
- hvac_type_cool = system.additionalProperties.getFeatureAsString(Constants.SizingInfoHVACCoolType)
3437
- hvac_types << hvac_type_cool.get if hvac_type_cool.is_initialized
3438
-
3439
- hvac_type_heat = system.additionalProperties.getFeatureAsString(Constants.SizingInfoHVACHeatType)
3440
- hvac_types << hvac_type_heat.get if hvac_type_heat.is_initialized
3441
- end
3442
-
3443
- ptacs = get_ptacs(model, thermal_zone)
3444
- ptacs.each do |ptac|
3445
- equipment << ptac
3446
- hvac_types << ptac.additionalProperties.getFeatureAsString(Constants.SizingInfoHVACCoolType).get
3447
- end
3448
-
3449
- evap_coolers = get_evap_coolers(model, thermal_zone)
3450
- evap_coolers.each do |evap_cooler|
3451
- equipment << evap_cooler
3452
- hvac_types << evap_cooler.additionalProperties.getFeatureAsString(Constants.SizingInfoHVACCoolType).get
3453
- end
3454
-
3455
- baseboards = get_baseboard_waters(model, thermal_zone)
3456
- baseboards.each do |baseboard|
3457
- equipment << baseboard
3458
- hvac_types << baseboard.additionalProperties.getFeatureAsString(Constants.SizingInfoHVACHeatType).get
3459
- end
3460
-
3461
- fancoils = get_fan_coils(model, thermal_zone)
3462
- fancoils.each do |fancoil|
3463
- equipment << fancoil
3464
- hvac_types << fancoil.additionalProperties.getFeatureAsString(Constants.SizingInfoHVACHeatType).get
3465
- end
3466
-
3467
- baseboards = get_baseboard_electrics(model, thermal_zone)
3468
- baseboards.each do |baseboard|
3469
- equipment << baseboard
3470
- hvac_types << baseboard.additionalProperties.getFeatureAsString(Constants.SizingInfoHVACHeatType).get
3471
- end
3472
-
3473
- unitary_system_hvac_map = get_unitary_system_hvac_map(model, thermal_zone)
3474
- unitary_system_hvac_map.each do |unitary_system_zone_hvac|
3475
- system, clg_coil, htg_coil = unitary_system_zone_hvac
3476
- next if htg_coil.nil?
3477
-
3478
- equipment << system
3479
- hvac_types << system.additionalProperties.getFeatureAsString(Constants.SizingInfoHVACHeatType).get
3480
- end
3481
-
3482
- ideal_air = get_ideal_air(model, thermal_zone)
3483
- if not ideal_air.nil?
3484
- equipment << ideal_air
3485
- hvac_types << ideal_air.additionalProperties.getFeatureAsString(Constants.SizingInfoHVACCoolType).get
3486
- hvac_types << ideal_air.additionalProperties.getFeatureAsString(Constants.SizingInfoHVACHeatType).get
3487
- end
3488
- return equipment
3489
- end
3490
-
3491
- def self.get_coils_from_hvac_equip(model, hvac_equip)
3492
- # Returns the clg coil, htg coil, and supp htg coil as applicable
3493
- clg_coil = nil
3494
- htg_coil = nil
3495
- supp_htg_coil = nil
3496
- if hvac_equip.is_a? OpenStudio::Model::AirLoopHVACUnitarySystem
3497
- htg_coil = get_coil_from_hvac_component(hvac_equip.heatingCoil)
3498
- clg_coil = get_coil_from_hvac_component(hvac_equip.coolingCoil)
3499
- supp_htg_coil = get_coil_from_hvac_component(hvac_equip.supplementalHeatingCoil)
3500
- elsif hvac_equip.is_a? OpenStudio::Model::ZoneHVACBaseboardConvectiveWater
3501
- htg_coil = get_coil_from_hvac_component(hvac_equip.heatingCoil)
3502
- elsif hvac_equip.is_a? OpenStudio::Model::ZoneHVACFourPipeFanCoil
3503
- htg_coil = get_coil_from_hvac_component(hvac_equip.heatingCoil)
3504
- elsif hvac_equip.is_a? OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner
3505
- htg_coil = get_coil_from_hvac_component(hvac_equip.heatingCoil)
3506
- if (not htg_coil.nil?) && (htg_coil.availabilitySchedule == model.alwaysOffDiscreteSchedule)
3507
- # Don't return coil if it is unused
3508
- htg_coil = nil
3509
- end
3510
- clg_coil = get_coil_from_hvac_component(hvac_equip.coolingCoil)
3511
- end
3512
- return clg_coil, htg_coil, supp_htg_coil
3513
- end
3514
-
3515
- def self.get_coil_from_hvac_component(hvac_component)
3516
- # Check for optional objects
3517
- if hvac_component.is_a? OpenStudio::Model::OptionalHVACComponent
3518
- return if not hvac_component.is_initialized
3519
-
3520
- hvac_component = hvac_component.get
3521
- end
3522
-
3523
- # Cooling coils
3524
- if hvac_component.to_CoilCoolingDXSingleSpeed.is_initialized
3525
- return hvac_component.to_CoilCoolingDXSingleSpeed.get
3526
- elsif hvac_component.to_CoilCoolingDXMultiSpeed.is_initialized
3527
- return hvac_component.to_CoilCoolingDXMultiSpeed.get
3528
- elsif hvac_component.to_CoilCoolingWaterToAirHeatPumpEquationFit.is_initialized
3529
- return hvac_component.to_CoilCoolingWaterToAirHeatPumpEquationFit.get
3530
- end
3531
-
3532
- # Heating coils
3533
- if hvac_component.to_CoilHeatingDXSingleSpeed.is_initialized
3534
- return hvac_component.to_CoilHeatingDXSingleSpeed.get
3535
- elsif hvac_component.to_CoilHeatingDXMultiSpeed.is_initialized
3536
- return hvac_component.to_CoilHeatingDXMultiSpeed.get
3537
- elsif hvac_component.to_CoilHeatingGas.is_initialized
3538
- return hvac_component.to_CoilHeatingGas.get
3539
- elsif hvac_component.to_CoilHeatingElectric.is_initialized
3540
- return hvac_component.to_CoilHeatingElectric.get
3541
- elsif hvac_component.to_CoilHeatingWaterBaseboard.is_initialized
3542
- return hvac_component.to_CoilHeatingWaterBaseboard.get
3543
- elsif hvac_component.to_CoilHeatingWater.is_initialized
3544
- return hvac_component.to_CoilHeatingWater.get
3545
- elsif hvac_component.to_CoilHeatingWaterToAirHeatPumpEquationFit.is_initialized
3546
- return hvac_component.to_CoilHeatingWaterToAirHeatPumpEquationFit.get
3547
- end
3548
-
3549
- return hvac_component
3550
- end
3551
-
3552
3169
  def self.get_unitary_system_from_air_loop_hvac(air_loop)
3553
3170
  # Returns the unitary system or nil
3554
3171
  air_loop.supplyComponents.each do |comp|
@@ -3559,201 +3176,52 @@ class HVAC
3559
3176
  return
3560
3177
  end
3561
3178
 
3562
- def self.get_evap_cooler_from_air_loop_hvac(air_loop)
3563
- # Returns the evap cooler or nil
3564
- air_loop.supplyComponents.each do |comp|
3565
- next unless comp.to_EvaporativeCoolerDirectResearchSpecial.is_initialized
3179
+ def self.set_cool_rated_cfm_per_ton_mshp(heat_pump, num_speeds)
3180
+ hp_ap = heat_pump.additional_properties
3566
3181
 
3567
- return comp.to_EvaporativeCoolerDirectResearchSpecial.get
3568
- end
3569
- return
3570
- end
3571
-
3572
- def self.get_unitary_system_air_loops(model, thermal_zone)
3573
- # Returns the unitary system(s), cooling coil(s), heating coil(s), and air loops(s) if available
3574
- unitary_system_air_loops = []
3575
- thermal_zone.airLoopHVACs.each do |air_loop|
3576
- system = get_unitary_system_from_air_loop_hvac(air_loop)
3577
- next if system.nil?
3578
-
3579
- clg_coil = nil
3580
- htg_coil = nil
3581
- if system.coolingCoil.is_initialized
3582
- clg_coil = system.coolingCoil.get
3583
- end
3584
- if system.heatingCoil.is_initialized
3585
- htg_coil = system.heatingCoil.get
3586
- end
3587
- unitary_system_air_loops << [system, clg_coil, htg_coil, air_loop]
3588
- end
3589
- return unitary_system_air_loops
3590
- end
3591
-
3592
- def self.get_unitary_system_hvac_map(model, thermal_zone)
3593
- # Returns the unitary system, cooling coil, and heating coil if available
3594
- unitary_system_hvac_map = []
3595
- thermal_zone.equipment.each do |equipment|
3596
- next unless equipment.to_AirLoopHVACUnitarySystem.is_initialized
3597
-
3598
- system = equipment.to_AirLoopHVACUnitarySystem.get
3599
- clg_coil = nil
3600
- htg_coil = nil
3601
- if system.coolingCoil.is_initialized
3602
- clg_coil = system.coolingCoil.get
3603
- end
3604
- if system.heatingCoil.is_initialized
3605
- htg_coil = system.heatingCoil.get
3606
- end
3607
- unitary_system_hvac_map << [system, clg_coil, htg_coil]
3608
- end
3609
- return unitary_system_hvac_map
3610
- end
3611
-
3612
- def self.get_ptacs(model, thermal_zone)
3613
- # Returns the PTAC(s) if available
3614
- ptacs = []
3615
- model.getZoneHVACPackagedTerminalAirConditioners.each do |ptac|
3616
- next unless thermal_zone.handle.to_s == ptac.thermalZone.get.handle.to_s
3617
-
3618
- ptacs << ptac
3619
- end
3620
- return ptacs
3621
- end
3622
-
3623
- def self.get_evap_coolers(model, thermal_zone)
3624
- # Returns the evaporative cooler if available
3625
- evap_coolers = []
3626
- thermal_zone.airLoopHVACs.each do |air_loop|
3627
- evap_cooler = get_evap_cooler_from_air_loop_hvac(air_loop)
3628
- next if evap_cooler.nil?
3629
-
3630
- evap_coolers << evap_cooler
3631
- end
3632
- return evap_coolers
3633
- end
3634
-
3635
- def self.get_baseboard_waters(model, thermal_zone)
3636
- # Returns the water baseboard if available
3637
- baseboards = []
3638
- model.getZoneHVACBaseboardConvectiveWaters.each do |baseboard|
3639
- next unless thermal_zone.handle.to_s == baseboard.thermalZone.get.handle.to_s
3640
-
3641
- baseboards << baseboard
3642
- end
3643
- return baseboards
3644
- end
3645
-
3646
- def self.get_fan_coils(model, thermal_zone)
3647
- # Returns the fan coil if available
3648
- fancoils = []
3649
- model.getZoneHVACFourPipeFanCoils.each do |fancoil|
3650
- next unless thermal_zone.handle.to_s == fancoil.thermalZone.get.handle.to_s
3651
-
3652
- fancoils << fancoil
3653
- end
3654
- return fancoils
3655
- end
3656
-
3657
- def self.get_baseboard_electrics(model, thermal_zone)
3658
- # Returns the electric baseboard if available
3659
- baseboards = []
3660
- model.getZoneHVACBaseboardConvectiveElectrics.each do |baseboard|
3661
- next unless thermal_zone.handle.to_s == baseboard.thermalZone.get.handle.to_s
3662
-
3663
- baseboards << baseboard
3664
- end
3665
- return baseboards
3666
- end
3667
-
3668
- def self.get_dehumidifiers(model, runner, thermal_zone)
3669
- # Returns the dehumidifier if available
3670
- dehums = []
3671
- model.getZoneHVACDehumidifierDXs.each do |dehum|
3672
- next unless thermal_zone.handle.to_s == dehum.thermalZone.get.handle.to_s
3673
-
3674
- dehums << dehum
3675
- end
3676
- return dehums
3677
- end
3678
-
3679
- def self.get_ideal_air(model, thermal_zone)
3680
- # Returns the heating ideal air loads system if available
3681
- model.getZoneHVACIdealLoadsAirSystems.each do |ideal_air|
3682
- next unless thermal_zone.handle.to_s == ideal_air.thermalZone.get.handle.to_s
3683
-
3684
- return ideal_air
3685
- end
3686
- return
3687
- end
3688
-
3689
- def self.has_ducted_equipment(model, air_loop)
3690
- if air_loop.name.to_s.include? Constants.ObjectNameEvaporativeCooler
3691
- system = air_loop
3692
- else
3693
- system = get_unitary_system_from_air_loop_hvac(air_loop)
3694
- end
3695
-
3696
- hvac_type_cool = system.additionalProperties.getFeatureAsString(Constants.SizingInfoHVACCoolType)
3697
- hvac_type_cool = hvac_type_cool.get if hvac_type_cool.is_initialized
3698
- hvac_type_heat = system.additionalProperties.getFeatureAsString(Constants.SizingInfoHVACHeatType)
3699
- hvac_type_heat = hvac_type_heat.get if hvac_type_heat.is_initialized
3700
-
3701
- if [Constants.ObjectNameCentralAirConditioner,
3702
- Constants.ObjectNameAirSourceHeatPump,
3703
- Constants.ObjectNameGroundSourceHeatPump].include? hvac_type_cool
3704
- return true
3705
- elsif Constants.ObjectNameFurnace == hvac_type_heat
3706
- return true
3707
- elsif [Constants.ObjectNameMiniSplitHeatPump, Constants.ObjectNameEvaporativeCooler].include? hvac_type_cool
3708
- is_ducted = system.additionalProperties.getFeatureAsBoolean(Constants.SizingInfoHVACSystemIsDucted).get
3709
- if is_ducted
3710
- return true
3711
- end
3712
- end
3713
-
3714
- return false
3715
- end
3716
-
3717
- def self.calc_mshp_cfms_ton_cooling(cap_min_per, cap_max_per, cfm_ton_min, cfm_ton_max, num_speeds, dB_rated, wB_rated, shr)
3718
- cool_capacity_ratios = [0.0] * num_speeds
3719
- cool_cfms_ton_rated = [0.0] * num_speeds
3720
- cool_shrs_rated = [0.0] * num_speeds
3182
+ dB_rated = 80.0 # deg-F
3183
+ wB_rated = 67.0 # deg-F
3721
3184
 
3722
- cap_nom_per = 1.0
3723
- cfm_ton_nom = ((cfm_ton_max - cfm_ton_min) / (cap_max_per - cap_min_per)) * (cap_nom_per - cap_min_per) + cfm_ton_min
3185
+ cool_nominal_capacity_ratio = 1.0
3186
+ cool_nominal_cfm_per_ton = ((hp_ap.cool_max_cfm_per_ton * hp_ap.cool_max_capacity_ratio - hp_ap.cool_min_cfm_per_ton * hp_ap.cool_min_capacity_ratio) /
3187
+ (hp_ap.cool_max_capacity_ratio - hp_ap.cool_min_capacity_ratio)) *
3188
+ (cool_nominal_capacity_ratio - hp_ap.cool_min_capacity_ratio) + hp_ap.cool_min_cfm_per_ton * hp_ap.cool_min_capacity_ratio
3724
3189
 
3725
3190
  p_atm = 14.696 # standard atmospheric pressure (psia)
3726
3191
 
3727
- ao = Psychrometrics.CoilAoFactor(dB_rated, wB_rated, p_atm, UnitConversions.convert(1, 'ton', 'kBtu/hr'), cfm_ton_nom, shr)
3192
+ ao = Psychrometrics.CoilAoFactor(dB_rated, wB_rated, p_atm, UnitConversions.convert(1, 'ton', 'kBtu/hr'), cool_nominal_cfm_per_ton, heat_pump.cooling_shr)
3193
+
3194
+ hp_ap.cool_capacity_ratios = []
3195
+ hp_ap.cool_rated_cfm_per_ton = []
3196
+ hp_ap.cool_rated_shrs_gross = []
3728
3197
 
3729
3198
  (0...num_speeds).each do |i|
3730
- cool_capacity_ratios[i] = cap_min_per + i * (cap_max_per - cap_min_per) / (num_speeds - 1)
3731
- cool_cfms_ton_rated[i] = cfm_ton_min + i * (cfm_ton_max - cfm_ton_min) / (num_speeds - 1)
3199
+ hp_ap.cool_capacity_ratios << hp_ap.cool_min_capacity_ratio + i * (hp_ap.cool_max_capacity_ratio - hp_ap.cool_min_capacity_ratio) / (num_speeds - 1)
3200
+ hp_ap.cool_rated_cfm_per_ton << (hp_ap.cool_min_cfm_per_ton * hp_ap.cool_min_capacity_ratio + i * (hp_ap.cool_max_cfm_per_ton * hp_ap.cool_max_capacity_ratio - hp_ap.cool_min_cfm_per_ton * hp_ap.cool_min_capacity_ratio) / (num_speeds - 1)) / hp_ap.cool_capacity_ratios[-1]
3732
3201
  # Calculate the SHR for each speed. Use minimum value of 0.98 to prevent E+ bypass factor calculation errors
3733
- cool_shrs_rated[i] = [Psychrometrics.CalculateSHR(dB_rated, wB_rated, p_atm, UnitConversions.convert(cool_capacity_ratios[i], 'ton', 'kBtu/hr'), cool_cfms_ton_rated[i], ao), 0.98].min
3202
+ hp_ap.cool_rated_shrs_gross[i] = [Psychrometrics.CalculateSHR(dB_rated, wB_rated, p_atm, UnitConversions.convert(hp_ap.cool_capacity_ratios[i], 'ton', 'kBtu/hr'), hp_ap.cool_rated_cfm_per_ton[i] * hp_ap.cool_capacity_ratios[i], ao), 0.98].min
3734
3203
  end
3735
-
3736
- return cool_cfms_ton_rated, cool_capacity_ratios, cool_shrs_rated
3737
3204
  end
3738
3205
 
3739
- def self.calc_mshp_cool_eirs(runner, seer, fan_power, c_d, num_speeds, cool_capacity_ratios, cool_cfms_ton_rated, cool_eir_ft_spec, cool_cap_ft_spec)
3206
+ def self.set_cool_rated_eirs_mshp(cooling_system, num_speeds)
3207
+ clg_ap = cooling_system.additional_properties
3208
+
3740
3209
  cops_norm = [1.901, 1.859, 1.746, 1.609, 1.474, 1.353, 1.247, 1.156, 1.079, 1.0]
3741
3210
  fan_powers_norm = [0.604, 0.634, 0.670, 0.711, 0.754, 0.800, 0.848, 0.898, 0.948, 1.0]
3742
3211
 
3743
- cool_eirs = [0.0] * num_speeds
3744
- fan_powers_rated = [0.0] * num_speeds
3745
- eers_Rated = [0.0] * num_speeds
3212
+ cop_max_speed = 3.5 # 3.5 is an initial guess, final value solved for below
3746
3213
 
3747
- cop_maxSpeed = 3.5 # 3.5 is an initial guess, final value solved for below
3214
+ fan_powers_rated = []
3215
+ eers_rated = []
3748
3216
 
3749
3217
  (0...num_speeds).each do |i|
3750
- fan_powers_rated[i] = fan_power * fan_powers_norm[i]
3751
- eers_Rated[i] = UnitConversions.convert(cop_maxSpeed, 'W', 'Btu/hr') * cops_norm[i]
3218
+ fan_powers_rated << clg_ap.fan_power_rated * fan_powers_norm[i]
3219
+ eers_rated << UnitConversions.convert(cop_max_speed, 'W', 'Btu/hr') * cops_norm[i]
3752
3220
  end
3753
3221
 
3754
- cop_maxSpeed_1 = cop_maxSpeed
3755
- cop_maxSpeed_2 = cop_maxSpeed
3756
- error = seer - calc_mshp_seer_4speed(eers_Rated, c_d, cool_capacity_ratios, cool_cfms_ton_rated, fan_powers_rated, true, cool_eir_ft_spec, cool_cap_ft_spec)
3222
+ cop_max_speed_1 = cop_max_speed
3223
+ cop_max_speed_2 = cop_max_speed
3224
+ error = cooling_system.cooling_efficiency_seer - calc_mshp_seer(eers_rated, clg_ap.cool_c_d, clg_ap.cool_capacity_ratios, clg_ap.cool_rated_cfm_per_ton, fan_powers_rated, clg_ap.cool_eir_ft_spec, clg_ap.cool_cap_ft_spec)
3757
3225
  error1 = error
3758
3226
  error2 = error
3759
3227
 
@@ -3764,12 +3232,12 @@ class HVAC
3764
3232
  (1...itmax + 1).each do |n|
3765
3233
  final_n = n
3766
3234
  (0...num_speeds).each do |i|
3767
- eers_Rated[i] = UnitConversions.convert(cop_maxSpeed, 'W', 'Btu/hr') * cops_norm[i]
3235
+ eers_rated[i] = UnitConversions.convert(cop_max_speed, 'W', 'Btu/hr') * cops_norm[i]
3768
3236
  end
3769
3237
 
3770
- error = seer - calc_mshp_seer_4speed(eers_Rated, c_d, cool_capacity_ratios, cool_cfms_ton_rated, fan_powers_rated, true, cool_eir_ft_spec, cool_cap_ft_spec)
3238
+ error = cooling_system.cooling_efficiency_seer - calc_mshp_seer(eers_rated, clg_ap.cool_c_d, clg_ap.cool_capacity_ratios, clg_ap.cool_rated_cfm_per_ton, fan_powers_rated, clg_ap.cool_eir_ft_spec, clg_ap.cool_cap_ft_spec)
3771
3239
 
3772
- cop_maxSpeed, cvg, cop_maxSpeed_1, error1, cop_maxSpeed_2, error2 = MathTools.Iterate(cop_maxSpeed, error, cop_maxSpeed_1, error1, cop_maxSpeed_2, error2, n, cvg)
3240
+ cop_max_speed, cvg, cop_max_speed_1, error1, cop_max_speed_2, error2 = MathTools.Iterate(cop_max_speed, error, cop_max_speed_1, error1, cop_max_speed_2, error2, n, cvg)
3773
3241
 
3774
3242
  if cvg
3775
3243
  break
@@ -3777,19 +3245,55 @@ class HVAC
3777
3245
  end
3778
3246
 
3779
3247
  if (not cvg) || (final_n > itmax)
3780
- cop_maxSpeed = UnitConversions.convert(0.547 * seer - 0.104, 'Btu/hr', 'W') # Correlation developed from JonW's MatLab scripts. Only used if an eer cannot be found.
3781
- runner.registerWarning('Mini-split heat pump cop iteration failed to converge. Setting to default value.')
3248
+ cop_max_speed = UnitConversions.convert(0.547 * cooling_system.cooling_efficiency_seer - 0.104, 'Btu/hr', 'W') # Correlation developed from JonW's MatLab scripts. Only used if an eer cannot be found.
3782
3249
  end
3783
3250
 
3251
+ clg_ap.cool_rated_eirs = []
3252
+
3784
3253
  (0...num_speeds).each do |i|
3785
- cool_eirs[i] = calc_eir_from_eer(UnitConversions.convert(cop_maxSpeed, 'W', 'Btu/hr') * cops_norm[i], fan_powers_rated[i])
3254
+ clg_ap.cool_rated_eirs << calc_eir_from_eer(UnitConversions.convert(cop_max_speed, 'W', 'Btu/hr') * cops_norm[i], fan_powers_rated[i])
3786
3255
  end
3256
+ end
3787
3257
 
3788
- return cool_eirs
3258
+ def self.set_mshp_downselected_speed_indices(heat_pump)
3259
+ hp_ap = heat_pump.additional_properties
3260
+
3261
+ # Down-select to speed indices
3262
+
3263
+ # Cooling
3264
+ hp_ap.cool_cap_ft_spec = hp_ap.cool_cap_ft_spec.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3265
+ hp_ap.cool_eir_ft_spec = hp_ap.cool_eir_ft_spec.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3266
+ hp_ap.cool_cap_fflow_spec = hp_ap.cool_cap_fflow_spec.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3267
+ hp_ap.cool_eir_fflow_spec = hp_ap.cool_eir_fflow_spec.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3268
+ hp_ap.cool_plf_fplr_spec = hp_ap.cool_plf_fplr_spec.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3269
+ hp_ap.cool_rated_cfm_per_ton = hp_ap.cool_rated_cfm_per_ton.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3270
+ hp_ap.cool_capacity_ratios = hp_ap.cool_capacity_ratios.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3271
+ hp_ap.cool_rated_shrs_gross = hp_ap.cool_rated_shrs_gross.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3272
+ hp_ap.cool_rated_eirs = hp_ap.cool_rated_eirs.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3273
+ hp_ap.cool_fan_speed_ratios = []
3274
+ for i in 0..(hp_ap.speed_indices.size - 1)
3275
+ hp_ap.cool_fan_speed_ratios << hp_ap.cool_rated_cfm_per_ton[i] * hp_ap.cool_capacity_ratios[i] / (hp_ap.cool_rated_cfm_per_ton[-1] * hp_ap.cool_capacity_ratios[-1])
3276
+ end
3277
+
3278
+ if heat_pump.is_a? HPXML::HeatPump # Skip for mini-split air conditioner
3279
+ # Heating
3280
+ hp_ap.heat_eir_ft_spec = hp_ap.heat_eir_ft_spec.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3281
+ hp_ap.heat_cap_fflow_spec = hp_ap.heat_cap_fflow_spec.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3282
+ hp_ap.heat_eir_fflow_spec = hp_ap.heat_eir_fflow_spec.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3283
+ hp_ap.heat_cap_ft_spec = hp_ap.heat_cap_ft_spec.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3284
+ hp_ap.heat_plf_fplr_spec = hp_ap.heat_plf_fplr_spec.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3285
+ hp_ap.heat_rated_cfm_per_ton = hp_ap.heat_rated_cfm_per_ton.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3286
+ hp_ap.heat_capacity_ratios = hp_ap.heat_capacity_ratios.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3287
+ hp_ap.heat_rated_eirs = hp_ap.heat_rated_eirs.select.with_index { |x, i| hp_ap.speed_indices.include? i }
3288
+ hp_ap.heat_fan_speed_ratios = []
3289
+ for i in 0..(hp_ap.speed_indices.size - 1)
3290
+ hp_ap.heat_fan_speed_ratios << hp_ap.heat_rated_cfm_per_ton[i] * hp_ap.heat_capacity_ratios[i] / (hp_ap.heat_rated_cfm_per_ton[-1] * hp_ap.heat_capacity_ratios[-1])
3291
+ end
3292
+ end
3789
3293
  end
3790
3294
 
3791
- def self.calc_mshp_seer_4speed(eer_a, c_d, capacity_ratio, cfm_tons, fan_power_rated, is_heat_pump, cool_eir_ft_spec, cool_cap_ft_spec)
3792
- n_max = (eer_a.length - 1.0) - 3.0 # Don't use max speed; FIXME: this is different than calc_mshp_hspf_4speed?
3295
+ def self.calc_mshp_seer(eer_a, c_d, capacity_ratio, cfm_tons, fan_power_rated, cool_eir_ft_spec, cool_cap_ft_spec)
3296
+ n_max = (eer_a.length - 1.0) - 3.0 # Don't use max speed; FIXME: this is different than calc_mshp_hspf?
3793
3297
  n_min = 0
3794
3298
  n_int = (n_min + (n_max - n_min) / 3.0).ceil.to_i
3795
3299
 
@@ -3814,17 +3318,17 @@ class HVAC
3814
3318
  q_B1 = capacity_ratio[n_min] * MathTools.biquadratic(wBin, tout_B, cool_cap_ft_spec[n_min])
3815
3319
  q_F1 = capacity_ratio[n_min] * MathTools.biquadratic(wBin, tout_F, cool_cap_ft_spec[n_min])
3816
3320
 
3817
- q_A2_net = q_A2 - fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3818
- q_B2_net = q_B2 - fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3819
- q_Ev_net = q_Ev - fan_power_rated[n_int] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_int] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3820
- q_B1_net = q_B1 - fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3821
- q_F1_net = q_F1 - fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3321
+ q_A2_net = q_A2 - fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * (cfm_tons[n_max] * capacity_ratio[n_max]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
3322
+ q_B2_net = q_B2 - fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * (cfm_tons[n_max] * capacity_ratio[n_max]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
3323
+ q_Ev_net = q_Ev - fan_power_rated[n_int] * UnitConversions.convert(1, 'W', 'Btu/hr') * (cfm_tons[n_int] * capacity_ratio[n_int]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
3324
+ q_B1_net = q_B1 - fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * (cfm_tons[n_min] * capacity_ratio[n_min]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
3325
+ q_F1_net = q_F1 - fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * (cfm_tons[n_min] * capacity_ratio[n_min]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
3822
3326
 
3823
- p_A2 = UnitConversions.convert(q_A2 * eir_A2, 'Btu', 'Wh') + fan_power_rated[n_max] * cfm_tons[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3824
- p_B2 = UnitConversions.convert(q_B2 * eir_B2, 'Btu', 'Wh') + fan_power_rated[n_max] * cfm_tons[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3825
- p_Ev = UnitConversions.convert(q_Ev * eir_Ev, 'Btu', 'Wh') + fan_power_rated[n_int] * cfm_tons[n_int] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3826
- p_B1 = UnitConversions.convert(q_B1 * eir_B1, 'Btu', 'Wh') + fan_power_rated[n_min] * cfm_tons[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3827
- p_F1 = UnitConversions.convert(q_F1 * eir_F1, 'Btu', 'Wh') + fan_power_rated[n_min] * cfm_tons[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3327
+ p_A2 = UnitConversions.convert(q_A2 * eir_A2, 'Btu', 'Wh') + fan_power_rated[n_max] * (cfm_tons[n_max] * capacity_ratio[n_max]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
3328
+ p_B2 = UnitConversions.convert(q_B2 * eir_B2, 'Btu', 'Wh') + fan_power_rated[n_max] * (cfm_tons[n_max] * capacity_ratio[n_max]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
3329
+ p_Ev = UnitConversions.convert(q_Ev * eir_Ev, 'Btu', 'Wh') + fan_power_rated[n_int] * (cfm_tons[n_int] * capacity_ratio[n_int]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
3330
+ p_B1 = UnitConversions.convert(q_B1 * eir_B1, 'Btu', 'Wh') + fan_power_rated[n_min] * (cfm_tons[n_min] * capacity_ratio[n_min]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
3331
+ p_F1 = UnitConversions.convert(q_F1 * eir_F1, 'Btu', 'Wh') + fan_power_rated[n_min] * (cfm_tons[n_min] * capacity_ratio[n_min]) / UnitConversions.convert(1, 'ton', 'Btu/hr')
3828
3332
 
3829
3333
  q_k1_87 = q_F1_net + (q_B1_net - q_F1_net) / (82.0 - 67.0) * (87 - 67.0)
3830
3334
  q_k2_87 = q_B2_net + (q_A2_net - q_B2_net) / (95.0 - 82.0) * (87.0 - 82.0)
@@ -3894,36 +3398,37 @@ class HVAC
3894
3398
  return seer
3895
3399
  end
3896
3400
 
3897
- def self.calc_mshp_cfms_ton_heating(cap_min_per, cap_max_per, cfm_ton_min, cfm_ton_max, num_speeds)
3898
- heat_capacity_ratios = [0.0] * num_speeds
3899
- heat_cfms_ton_rated = [0.0] * num_speeds
3401
+ def self.set_heat_rated_cfm_per_ton_mshp(heat_pump, num_speeds)
3402
+ hp_ap = heat_pump.additional_properties
3403
+
3404
+ hp_ap.heat_capacity_ratios = []
3405
+ hp_ap.heat_rated_cfm_per_ton = []
3900
3406
 
3901
3407
  (0...num_speeds).each do |i|
3902
- heat_capacity_ratios[i] = cap_min_per + i * (cap_max_per - cap_min_per) / (num_speeds - 1)
3903
- heat_cfms_ton_rated[i] = cfm_ton_min + i * (cfm_ton_max - cfm_ton_min) / (num_speeds - 1)
3408
+ hp_ap.heat_capacity_ratios << hp_ap.heat_min_capacity_ratio + i * (hp_ap.heat_max_capacity_ratio - hp_ap.heat_min_capacity_ratio) / (num_speeds - 1)
3409
+ hp_ap.heat_rated_cfm_per_ton << (hp_ap.heat_min_cfm_per_ton * hp_ap.heat_min_capacity_ratio + i * (hp_ap.heat_max_cfm_per_ton * hp_ap.heat_max_capacity_ratio - hp_ap.heat_min_cfm_per_ton * hp_ap.heat_min_capacity_ratio) / (num_speeds - 1)) / hp_ap.heat_capacity_ratios[-1]
3904
3410
  end
3905
-
3906
- return heat_cfms_ton_rated, heat_capacity_ratios
3907
3411
  end
3908
3412
 
3909
- def self.calc_mshp_heat_eirs(runner, hspf, fan_power, hp_min_temp, c_d, cool_cfms_ton_rated, num_speeds, heat_capacity_ratios, heat_cfms_ton_rated, heat_eir_ft_spec, heat_cap_ft_spec)
3910
- cops_norm = [1.792, 1.502, 1.308, 1.207, 1.145, 1.105, 1.077, 1.056, 1.041, 1]
3911
- fan_powers_norm = [0.577, 0.625, 0.673, 0.720, 0.768, 0.814, 0.861, 0.907, 0.954, 1]
3413
+ def self.set_heat_rated_eirs_mshp(heat_pump, num_speeds)
3414
+ hp_ap = heat_pump.additional_properties
3912
3415
 
3913
- heat_eirs = [0.0] * num_speeds
3914
- fan_powers_rated = [0.0] * num_speeds
3915
- cops_rated = [0.0] * num_speeds
3416
+ cops_norm = [1.792, 1.502, 1.308, 1.207, 1.145, 1.105, 1.077, 1.056, 1.041, 1.0]
3417
+ fan_powers_norm = [0.577, 0.625, 0.673, 0.720, 0.768, 0.814, 0.861, 0.907, 0.954, 1.0]
3916
3418
 
3917
- cop_maxSpeed = 3.25 # 3.35 is an initial guess, final value solved for below
3419
+ cop_max_speed = 3.25 # 3.35 is an initial guess, final value solved for below
3420
+
3421
+ fan_powers_rated = []
3422
+ cops_rated = []
3918
3423
 
3919
3424
  (0...num_speeds).each do |i|
3920
- fan_powers_rated[i] = fan_power * fan_powers_norm[i]
3921
- cops_rated[i] = cop_maxSpeed * cops_norm[i]
3425
+ fan_powers_rated << hp_ap.fan_power_rated * fan_powers_norm[i]
3426
+ cops_rated << cop_max_speed * cops_norm[i]
3922
3427
  end
3923
3428
 
3924
- cop_maxSpeed_1 = cop_maxSpeed
3925
- cop_maxSpeed_2 = cop_maxSpeed
3926
- error = hspf - calc_mshp_hspf_4speed(cops_rated, c_d, heat_capacity_ratios, heat_cfms_ton_rated, fan_powers_rated, hp_min_temp, heat_eir_ft_spec, heat_cap_ft_spec)
3429
+ cop_max_speed_1 = cop_max_speed
3430
+ cop_max_speed_2 = cop_max_speed
3431
+ error = heat_pump.heating_efficiency_hspf - calc_mshp_hspf(cops_rated, hp_ap.heat_c_d, hp_ap.heat_capacity_ratios, hp_ap.heat_rated_cfm_per_ton, fan_powers_rated, hp_ap.hp_min_temp, hp_ap.heat_eir_ft_spec, hp_ap.heat_cap_ft_spec)
3927
3432
 
3928
3433
  error1 = error
3929
3434
  error2 = error
@@ -3935,12 +3440,12 @@ class HVAC
3935
3440
  (1...itmax + 1).each do |n|
3936
3441
  final_n = n
3937
3442
  (0...num_speeds).each do |i|
3938
- cops_rated[i] = cop_maxSpeed * cops_norm[i]
3443
+ cops_rated[i] = cop_max_speed * cops_norm[i]
3939
3444
  end
3940
3445
 
3941
- error = hspf - calc_mshp_hspf_4speed(cops_rated, c_d, heat_capacity_ratios, cool_cfms_ton_rated, fan_powers_rated, hp_min_temp, heat_eir_ft_spec, heat_cap_ft_spec)
3446
+ error = heat_pump.heating_efficiency_hspf - calc_mshp_hspf(cops_rated, hp_ap.heat_c_d, hp_ap.heat_capacity_ratios, hp_ap.heat_rated_cfm_per_ton, fan_powers_rated, hp_ap.hp_min_temp, hp_ap.heat_eir_ft_spec, hp_ap.heat_cap_ft_spec)
3942
3447
 
3943
- cop_maxSpeed, cvg, cop_maxSpeed_1, error1, cop_maxSpeed_2, error2 = MathTools.Iterate(cop_maxSpeed, error, cop_maxSpeed_1, error1, cop_maxSpeed_2, error2, n, cvg)
3448
+ cop_max_speed, cvg, cop_max_speed_1, error1, cop_max_speed_2, error2 = MathTools.Iterate(cop_max_speed, error, cop_max_speed_1, error1, cop_max_speed_2, error2, n, cvg)
3944
3449
 
3945
3450
  if cvg
3946
3451
  break
@@ -3948,19 +3453,62 @@ class HVAC
3948
3453
  end
3949
3454
 
3950
3455
  if (not cvg) || (final_n > itmax)
3951
- cop_maxSpeed = UnitConversions.convert(0.4174 * hspf - 1.1134, 'Btu/hr', 'W') # Correlation developed from JonW's MatLab scripts. Only used if a cop cannot be found.
3952
- runner.registerWarning('Mini-split heat pump cop iteration failed to converge. Setting to default value.')
3456
+ cop_max_speed = UnitConversions.convert(0.4174 * hspf - 1.1134, 'Btu/hr', 'W') # Correlation developed from JonW's MatLab scripts. Only used if a cop cannot be found.
3953
3457
  end
3954
3458
 
3459
+ hp_ap.heat_rated_eirs = []
3955
3460
  (0...num_speeds).each do |i|
3956
- heat_eirs[i] = calc_eir_from_cop(cop_maxSpeed * cops_norm[i], fan_powers_rated[i])
3461
+ hp_ap.heat_rated_eirs << calc_eir_from_cop(cop_max_speed * cops_norm[i], fan_powers_rated[i])
3957
3462
  end
3463
+ end
3464
+
3465
+ def self.set_gshp_assumptions(heat_pump, weather)
3466
+ hp_ap = heat_pump.additional_properties
3958
3467
 
3959
- return heat_eirs
3468
+ hp_ap.design_chw = [85.0, weather.design.CoolingDrybulb - 15.0, weather.data.AnnualAvgDrybulb + 10.0].max # Temperature of water entering indoor coil,use 85F as lower bound
3469
+ hp_ap.design_delta_t = 10.0
3470
+ hp_ap.fluid_type = Constants.FluidPropyleneGlycol
3471
+ hp_ap.frac_glycol = 0.3
3472
+ if hp_ap.fluid_type == Constants.FluidWater
3473
+ hp_ap.design_hw = [45.0, weather.design.HeatingDrybulb + 35.0, weather.data.AnnualAvgDrybulb - 10.0].max # Temperature of fluid entering indoor coil, use 45F as lower bound for water
3474
+ else
3475
+ hp_ap.design_hw = [35.0, weather.design.HeatingDrybulb + 35.0, weather.data.AnnualAvgDrybulb - 10.0].min # Temperature of fluid entering indoor coil, use 35F as upper bound
3476
+ end
3477
+ hp_ap.ground_conductivity = 0.6 # Btu/h-ft-R
3478
+ hp_ap.ground_diffusivity = 0.0208
3479
+ hp_ap.grout_conductivity = 0.4 # Btu/h-ft-R
3480
+ hp_ap.bore_diameter = 5.0 # in
3481
+ hp_ap.pipe_size = 0.75 # in
3482
+ # Pipe nominal size conversion to pipe outside diameter and inside diameter,
3483
+ # only pipe sizes <= 2" are used here with DR11 (dimension ratio),
3484
+ if hp_ap.pipe_size == 0.75 # 3/4" pipe
3485
+ hp_ap.pipe_od = 1.050 # in
3486
+ hp_ap.pipe_id = 0.859 # in
3487
+ elsif hp_ap.pipe_size == 1.0 # 1" pipe
3488
+ hp_ap.pipe_od = 1.315 # in
3489
+ hp_ap.pipe_id = 1.076 # in
3490
+ elsif hp_ap.pipe_size == 1.25 # 1-1/4" pipe
3491
+ hp_ap.pipe_od = 1.660 # in
3492
+ hp_ap.pipe_id = 1.358 # in
3493
+ end
3494
+ hp_ap.pipe_cond = 0.23 # Btu/h-ft-R; Pipe thermal conductivity, default to high density polyethylene
3495
+ hp_ap.u_tube_spacing_type = 'b'
3496
+ # Calculate distance between pipes
3497
+ if hp_ap.u_tube_spacing_type == 'as'
3498
+ # Two tubes, spaced 1/8” apart at the center of the borehole
3499
+ hp_ap.u_tube_spacing = 0.125
3500
+ elsif hp_ap.u_tube_spacing_type == 'b'
3501
+ # Two tubes equally spaced between the borehole edges
3502
+ hp_ap.u_tube_spacing = 0.9661
3503
+ elsif hp_ap.u_tube_spacing_type == 'c'
3504
+ # Both tubes placed against outer edge of borehole
3505
+ hp_ap.u_tube_spacing = hp_ap.bore_diameter - 2 * hp_ap.pipe_od
3506
+ end
3507
+ hp_ap.shank_spacing = hp_ap.u_tube_spacing + hp_ap.pipe_od # Distance from center of pipe to center of pipe
3960
3508
  end
3961
3509
 
3962
- def self.calc_mshp_hspf_4speed(cop_47, c_d, capacity_ratio, cfm_tons, fan_power_rated, hp_min_temp, heat_eir_ft_spec, heat_cap_ft_spec)
3963
- n_max = (cop_47.length - 1.0) #-3 # Don't use max speed; FIXME: this is different than calc_mshp_seer_4speed?
3510
+ def self.calc_mshp_hspf(cop_47, c_d, capacity_ratio, cfm_tons, fan_power_rated, hp_min_temp, heat_eir_ft_spec, heat_cap_ft_spec)
3511
+ n_max = (cop_47.length - 1.0) #-3 # Don't use max speed; FIXME: this is different than calc_mshp_seer?
3964
3512
  n_min = 0
3965
3513
  n_int = (n_min + (n_max - n_min) / 3.0).ceil.to_i
3966
3514
 
@@ -3986,17 +3534,17 @@ class HVAC
3986
3534
  q_H1_1 = capacity_ratio[n_min]
3987
3535
  q_H0_1 = q_H1_1 * MathTools.biquadratic(tin, tout_0, heat_cap_ft_spec[n_min])
3988
3536
 
3989
- q_H1_2_net = q_H1_2 + fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3990
- q_H3_2_net = q_H3_2 + fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3991
- q_H2_v_net = q_H2_v + fan_power_rated[n_int] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_int] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3992
- q_H1_1_net = q_H1_1 + fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3993
- q_H0_1_net = q_H0_1 + fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3537
+ q_H1_2_net = q_H1_2 + fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] * capacity_ratio[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3538
+ q_H3_2_net = q_H3_2 + fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] * capacity_ratio[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3539
+ q_H2_v_net = q_H2_v + fan_power_rated[n_int] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_int] * capacity_ratio[n_int] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3540
+ q_H1_1_net = q_H1_1 + fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] * capacity_ratio[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3541
+ q_H0_1_net = q_H0_1 + fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] * capacity_ratio[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3994
3542
 
3995
- p_H1_2 = q_H1_2 * eir_H1_2 + fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3996
- p_H3_2 = q_H3_2 * eir_H3_2 + fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3997
- p_H2_v = q_H2_v * eir_H2_v + fan_power_rated[n_int] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_int] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3998
- p_H1_1 = q_H1_1 * eir_H1_1 + fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3999
- p_H0_1 = q_H0_1 * eir_H0_1 + fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3543
+ p_H1_2 = q_H1_2 * eir_H1_2 + fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] * capacity_ratio[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3544
+ p_H3_2 = q_H3_2 * eir_H3_2 + fan_power_rated[n_max] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_max] * capacity_ratio[n_max] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3545
+ p_H2_v = q_H2_v * eir_H2_v + fan_power_rated[n_int] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_int] * capacity_ratio[n_int] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3546
+ p_H1_1 = q_H1_1 * eir_H1_1 + fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] * capacity_ratio[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
3547
+ p_H0_1 = q_H0_1 * eir_H0_1 + fan_power_rated[n_min] * UnitConversions.convert(1, 'W', 'Btu/hr') * cfm_tons[n_min] * capacity_ratio[n_min] / UnitConversions.convert(1, 'ton', 'Btu/hr')
4000
3548
 
4001
3549
  q_H35_2 = 0.9 * (q_H3_2_net + 0.6 * (q_H1_2_net - q_H3_2_net))
4002
3550
  p_H35_2 = 0.985 * (p_H3_2 + 0.6 * (p_H1_2 - p_H3_2))
@@ -4109,34 +3657,42 @@ class HVAC
4109
3657
  return s
4110
3658
  end
4111
3659
 
4112
- def self.get_crankcase_assumptions(fraction_cool_load_served)
4113
- crankcase_kw = 0.05 * fraction_cool_load_served # From RESNET Publication No. 002-2017
4114
- crankcase_temp = 50.0 # From RESNET Publication No. 002-2017
4115
- return crankcase_kw, crankcase_temp
3660
+ def self.set_crankcase_assumptions(hvac_system)
3661
+ hvac_ap = hvac_system.additional_properties
3662
+
3663
+ if hvac_system.is_a?(HPXML::HeatPump) && (hvac_system.fraction_heat_load_served <= 0)
3664
+ hvac_ap.crankcase_kw = 0.0
3665
+ hvac_ap.crankcase_temp = nil
3666
+ elsif hvac_system.is_a?(HPXML::HeatPump) && (hvac_system.heat_pump_type == HPXML::HVACTypeHeatPumpMiniSplit)
3667
+ hvac_ap.crankcase_kw = 0.0
3668
+ hvac_ap.crankcase_temp = nil
3669
+ elsif hvac_system.is_a?(HPXML::CoolingSystem) && (hvac_system.cooling_system_type == HPXML::HVACTypeMiniSplitAirConditioner)
3670
+ hvac_ap.crankcase_kw = 0.0
3671
+ hvac_ap.crankcase_temp = nil
3672
+ else
3673
+ hvac_ap.crankcase_kw = 0.05 * hvac_system.fraction_cool_load_served # From RESNET Publication No. 002-2017
3674
+ hvac_ap.crankcase_temp = 50.0 # From RESNET Publication No. 002-2017
3675
+ end
4116
3676
  end
4117
3677
 
4118
- def self.get_heat_pump_temp_assumptions(heat_pump)
4119
- # Calculates:
4120
- # 1. Minimum temperature for HP compressor operation
4121
- # 2. Maximum temperature for HP supplemental heating operation
3678
+ def self.set_heat_pump_temperatures(heat_pump)
3679
+ hp_ap = heat_pump.additional_properties
3680
+
3681
+ # Sets:
3682
+ # 1. Minimum temperature (deg-F) for HP compressor operation
3683
+ # 2. Maximum temperature (deg-F) for HP supplemental heating operation
4122
3684
  if not heat_pump.backup_heating_switchover_temp.nil?
4123
- hp_min_temp = heat_pump.backup_heating_switchover_temp
4124
- supp_max_temp = heat_pump.backup_heating_switchover_temp
3685
+ hp_ap.hp_min_temp = heat_pump.backup_heating_switchover_temp
3686
+ hp_ap.supp_max_temp = heat_pump.backup_heating_switchover_temp
4125
3687
  else
4126
- supp_max_temp = 40.0
4127
- # Minimum temperature for Heat Pump operation:
4128
- if heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpMiniSplit
4129
- hp_min_temp = -30.0 # deg-F
4130
- else
4131
- hp_min_temp = 0.0 # deg-F
4132
- end
3688
+ hp_ap.supp_max_temp = 40.0
3689
+ hp_ap.hp_min_temp = -40.0
4133
3690
  end
4134
- return hp_min_temp, supp_max_temp
4135
3691
  end
4136
3692
 
4137
3693
  def self.get_default_duct_surface_area(duct_type, ncfl_ag, cfa_served, n_returns)
4138
3694
  # Fraction of primary ducts (ducts outside conditioned space)
4139
- f_out = (ncfl_ag == 1) ? 1.0 : 0.75
3695
+ f_out = (ncfl_ag <= 1) ? 1.0 : 0.75
4140
3696
 
4141
3697
  if duct_type == HPXML::DuctTypeSupply
4142
3698
  primary_duct_area = 0.27 * cfa_served * f_out
@@ -4171,25 +3727,271 @@ class HVAC
4171
3727
  return primary_duct_location, secondary_duct_location
4172
3728
  end
4173
3729
 
3730
+ def self.get_installation_quality_cooling_coeff(f_chg)
3731
+ if f_chg <= 0
3732
+ qgr_values = [-9.46E-01, 4.93E-02, -1.18E-03, -1.15E+00]
3733
+ p_values = [-3.13E-01, 1.15E-02, 2.66E-03, -1.16E-01]
3734
+ else
3735
+ qgr_values = [-1.63E-01, 1.14E-02, -2.10E-04, -1.40E-01]
3736
+ p_values = [2.19E-01, -5.01E-03, 9.89E-04, 2.84E-01]
3737
+ end
3738
+ ff_chg_values = [26.67, 35.0]
3739
+ return qgr_values, p_values, ff_chg_values
3740
+ end
3741
+
3742
+ def self.get_installation_quality_heating_coeff(f_chg)
3743
+ if f_chg <= 0
3744
+ qgr_values = [-0.0338595, 0.0202827, -2.6226343]
3745
+ p_values = [0.0615649, 0.0044554, -0.2598507]
3746
+ else
3747
+ qgr_values = [-0.0029514, 0.0007379, -0.0064112]
3748
+ p_values = [-0.0594134, 0.0159205, 1.8872153]
3749
+ end
3750
+ ff_chg_values = [8.33]
3751
+ return qgr_values, p_values, ff_chg_values
3752
+ end
3753
+
3754
+ def self.apply_installation_quality(model, heating_system, cooling_system, unitary_system, htg_coil, clg_coil, control_zone)
3755
+ if not cooling_system.nil?
3756
+ charge_defect_ratio = cooling_system.charge_defect_ratio
3757
+ cool_airflow_defect_ratio = cooling_system.airflow_defect_ratio
3758
+ end
3759
+ if not heating_system.nil?
3760
+ heat_airflow_defect_ratio = heating_system.airflow_defect_ratio
3761
+ end
3762
+ return if (charge_defect_ratio.to_f.abs < 0.001) && (cool_airflow_defect_ratio.to_f.abs < 0.001) && (heat_airflow_defect_ratio.to_f.abs < 0.001)
3763
+
3764
+ cool_airflow_rated_defect_ratio = []
3765
+ if (not clg_coil.nil?) && (cooling_system.fraction_cool_load_served > 0)
3766
+ clg_ap = cooling_system.additional_properties
3767
+ clg_cfm = cooling_system.cooling_airflow_cfm
3768
+ if clg_coil.to_CoilCoolingDXSingleSpeed.is_initialized
3769
+ cool_airflow_rated_defect_ratio = [UnitConversions.convert(clg_cfm, 'cfm', 'm^3/s') / clg_coil.ratedAirFlowRate.get - 1.0]
3770
+ elsif clg_coil.to_CoilCoolingDXMultiSpeed.is_initialized
3771
+ cool_airflow_rated_defect_ratio = clg_coil.stages.zip(clg_ap.cool_fan_speed_ratios).map { |stage, speed_ratio| UnitConversions.convert(clg_cfm * speed_ratio, 'cfm', 'm^3/s') / stage.ratedAirFlowRate.get - 1.0 }
3772
+ end
3773
+ end
3774
+
3775
+ heat_airflow_rated_defect_ratio = []
3776
+ if (not htg_coil.nil?) && (heating_system.fraction_heat_load_served > 0)
3777
+ htg_ap = heating_system.additional_properties
3778
+ htg_cfm = heating_system.heating_airflow_cfm
3779
+ if htg_coil.to_CoilHeatingDXSingleSpeed.is_initialized
3780
+ heat_airflow_rated_defect_ratio = [UnitConversions.convert(htg_cfm, 'cfm', 'm^3/s') / htg_coil.ratedAirFlowRate.get - 1.0]
3781
+ elsif htg_coil.to_CoilHeatingDXMultiSpeed.is_initialized
3782
+ heat_airflow_rated_defect_ratio = htg_coil.stages.zip(htg_ap.heat_fan_speed_ratios).map { |stage, speed_ratio| UnitConversions.convert(htg_cfm * speed_ratio, 'cfm', 'm^3/s') / stage.ratedAirFlowRate.get - 1.0 }
3783
+ end
3784
+ end
3785
+
3786
+ return if cool_airflow_rated_defect_ratio.empty? && heat_airflow_rated_defect_ratio.empty?
3787
+
3788
+ obj_name = "#{unitary_system.name} install quality"
3789
+
3790
+ tin_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Mean Air Temperature')
3791
+ tin_sensor.setName("#{obj_name} tin s")
3792
+ tin_sensor.setKeyName(control_zone.name.to_s)
3793
+
3794
+ tout_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Outdoor Air Drybulb Temperature')
3795
+ tout_sensor.setName("#{obj_name} tt s")
3796
+ tout_sensor.setKeyName(control_zone.name.to_s)
3797
+
3798
+ fault_program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
3799
+ fault_program.setName("#{obj_name} program")
3800
+
3801
+ f_chg = charge_defect_ratio.to_f
3802
+ fault_program.addLine("Set F_CH = #{f_chg.round(3)}")
3803
+
3804
+ if not cool_airflow_rated_defect_ratio.empty?
3805
+ if clg_coil.is_a? OpenStudio::Model::CoilCoolingDXSingleSpeed
3806
+ num_speeds = 1
3807
+ cool_cap_fff_curves = [clg_coil.totalCoolingCapacityFunctionOfFlowFractionCurve.to_CurveQuadratic.get]
3808
+ cool_eir_fff_curves = [clg_coil.energyInputRatioFunctionOfFlowFractionCurve.to_CurveQuadratic.get]
3809
+ elsif clg_coil.is_a? OpenStudio::Model::CoilCoolingDXMultiSpeed
3810
+ num_speeds = clg_coil.stages.size
3811
+ cool_cap_fff_curves = clg_coil.stages.map { |stage| stage.totalCoolingCapacityFunctionofFlowFractionCurve.to_CurveQuadratic.get }
3812
+ cool_eir_fff_curves = clg_coil.stages.map { |stage| stage.energyInputRatioFunctionofFlowFractionCurve.to_CurveQuadratic.get }
3813
+ else
3814
+ fail 'cooling coil not supported'
3815
+ end
3816
+ for speed in 0..(num_speeds - 1)
3817
+ cool_cap_fff_curve = cool_cap_fff_curves[speed]
3818
+ cool_cap_fff_act = OpenStudio::Model::EnergyManagementSystemActuator.new(cool_cap_fff_curve, 'Curve', 'Curve Result')
3819
+ cool_cap_fff_act.setName("#{obj_name} cap clg act")
3820
+
3821
+ cool_eir_fff_curve = cool_eir_fff_curves[speed]
3822
+ cool_eir_fff_act = OpenStudio::Model::EnergyManagementSystemActuator.new(cool_eir_fff_curve, 'Curve', 'Curve Result')
3823
+ cool_eir_fff_act.setName("#{obj_name} eir clg act")
3824
+
3825
+ # NOTE: heat pump (cooling) curves don't exhibit expected trends at extreme faults;
3826
+ fault_program.addLine("Set a1_AF_Qgr_c = #{cool_cap_fff_curve.coefficient1Constant}")
3827
+ fault_program.addLine("Set a2_AF_Qgr_c = #{cool_cap_fff_curve.coefficient2x}")
3828
+ fault_program.addLine("Set a3_AF_Qgr_c = #{cool_cap_fff_curve.coefficient3xPOW2}")
3829
+ fault_program.addLine("Set a1_AF_EIR_c = #{cool_eir_fff_curve.coefficient1Constant}")
3830
+ fault_program.addLine("Set a2_AF_EIR_c = #{cool_eir_fff_curve.coefficient2x}")
3831
+ fault_program.addLine("Set a3_AF_EIR_c = #{cool_eir_fff_curve.coefficient3xPOW2}")
3832
+
3833
+ qgr_values, p_values, ff_chg_values = get_installation_quality_cooling_coeff(f_chg)
3834
+
3835
+ fault_program.addLine("Set a1_CH_Qgr_c = #{qgr_values[0]}")
3836
+ fault_program.addLine("Set a2_CH_Qgr_c = #{qgr_values[1]}")
3837
+ fault_program.addLine("Set a3_CH_Qgr_c = #{qgr_values[2]}")
3838
+ fault_program.addLine("Set a4_CH_Qgr_c = #{qgr_values[3]}")
3839
+
3840
+ fault_program.addLine("Set a1_CH_P_c = #{p_values[0]}")
3841
+ fault_program.addLine("Set a2_CH_P_c = #{p_values[1]}")
3842
+ fault_program.addLine("Set a3_CH_P_c = #{p_values[2]}")
3843
+ fault_program.addLine("Set a4_CH_P_c = #{p_values[3]}")
3844
+
3845
+ ff_ch_c = 1.0 / (1.0 + (qgr_values[0] + (qgr_values[1] * ff_chg_values[0]) + (qgr_values[2] * ff_chg_values[1]) + (qgr_values[3] * f_chg)) * f_chg)
3846
+ fault_program.addLine("Set FF_CH_c = #{ff_ch_c.round(3)}")
3847
+
3848
+ fault_program.addLine('Set q0_CH = a1_CH_Qgr_c')
3849
+ fault_program.addLine("Set q1_CH = a2_CH_Qgr_c*#{tin_sensor.name}")
3850
+ fault_program.addLine("Set q2_CH = a3_CH_Qgr_c*#{tout_sensor.name}")
3851
+ fault_program.addLine('Set q3_CH = a4_CH_Qgr_c*F_CH')
3852
+ fault_program.addLine('Set Y_CH_Q_c = 1 + ((q0_CH+(q1_CH)+(q2_CH)+(q3_CH))*F_CH)')
3853
+
3854
+ fault_program.addLine('Set q0_AF_CH = a1_AF_Qgr_c')
3855
+ fault_program.addLine('Set q1_AF_CH = a2_AF_Qgr_c*FF_CH_c')
3856
+ fault_program.addLine('Set q2_AF_CH = a3_AF_Qgr_c*FF_CH_c*FF_CH_c')
3857
+ fault_program.addLine('Set p_CH_Q_c = Y_CH_Q_c/(q0_AF_CH+(q1_AF_CH)+(q2_AF_CH))')
3858
+
3859
+ fault_program.addLine('Set p1_CH = a1_CH_P_c')
3860
+ fault_program.addLine("Set p2_CH = a2_CH_P_c*#{tin_sensor.name}")
3861
+ fault_program.addLine("Set p3_CH = a3_CH_P_c*#{tout_sensor.name}")
3862
+ fault_program.addLine('Set p4_CH = a4_CH_P_c*F_CH')
3863
+ fault_program.addLine('Set Y_CH_COP_c = Y_CH_Q_c/(1 + (p1_CH+(p2_CH)+(p3_CH)+(p4_CH))*F_CH)')
3864
+
3865
+ fault_program.addLine('Set eir0_AF_CH = a1_AF_EIR_c')
3866
+ fault_program.addLine('Set eir1_AF_CH = a2_AF_EIR_c*FF_CH_c')
3867
+ fault_program.addLine('Set eir2_AF_CH = a3_AF_EIR_c*FF_CH_c*FF_CH_c')
3868
+ fault_program.addLine('Set p_CH_COP_c = Y_CH_COP_c*(eir0_AF_CH+(eir1_AF_CH)+(eir2_AF_CH))')
3869
+
3870
+ fault_program.addLine("Set FF_AF_c = 1.0 + #{cool_airflow_rated_defect_ratio[speed].round(3)}")
3871
+ fault_program.addLine('Set FF_AF_comb_c = FF_CH_c * FF_AF_c')
3872
+
3873
+ fault_program.addLine('Set q0_AF_comb = a1_AF_Qgr_c')
3874
+ fault_program.addLine('Set q1_AF_comb = a2_AF_Qgr_c*FF_AF_comb_c')
3875
+ fault_program.addLine('Set q2_AF_comb = a3_AF_Qgr_c*FF_AF_comb_c*FF_AF_comb_c')
3876
+ fault_program.addLine('Set p_AF_Q_c = q0_AF_comb+(q1_AF_comb)+(q2_AF_comb)')
3877
+
3878
+ fault_program.addLine('Set eir0_AF_comb = a1_AF_EIR_c')
3879
+ fault_program.addLine('Set eir1_AF_comb = a2_AF_EIR_c*FF_AF_comb_c')
3880
+ fault_program.addLine('Set eir2_AF_comb = a3_AF_EIR_c*FF_AF_comb_c*FF_AF_comb_c')
3881
+ fault_program.addLine('Set p_AF_COP_c = 1.0/(eir0_AF_comb+(eir1_AF_comb)+(eir2_AF_comb))')
3882
+
3883
+ fault_program.addLine("Set #{cool_cap_fff_act.name} = (p_CH_Q_c * p_AF_Q_c)")
3884
+ fault_program.addLine("Set #{cool_eir_fff_act.name} = (1.0 / (p_CH_COP_c * p_AF_COP_c))")
3885
+ end
3886
+ end
3887
+
3888
+ if not heat_airflow_rated_defect_ratio.empty?
3889
+
3890
+ if htg_coil.is_a? OpenStudio::Model::CoilHeatingDXSingleSpeed
3891
+ num_speeds = 1
3892
+ heat_cap_fff_curves = [htg_coil.totalHeatingCapacityFunctionofFlowFractionCurve.to_CurveQuadratic.get]
3893
+ heat_eir_fff_curves = [htg_coil.energyInputRatioFunctionofFlowFractionCurve.to_CurveQuadratic.get]
3894
+ elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingDXMultiSpeed
3895
+ num_speeds = htg_coil.stages.size
3896
+ heat_cap_fff_curves = htg_coil.stages.map { |stage| stage.heatingCapacityFunctionofFlowFractionCurve.to_CurveQuadratic.get }
3897
+ heat_eir_fff_curves = htg_coil.stages.map { |stage| stage.energyInputRatioFunctionofFlowFractionCurve.to_CurveQuadratic.get }
3898
+ else
3899
+ fail 'heating coil not supported'
3900
+ end
3901
+ for speed in 0..(num_speeds - 1)
3902
+ heat_cap_fff_curve = heat_cap_fff_curves[speed]
3903
+ heat_cap_fff_act = OpenStudio::Model::EnergyManagementSystemActuator.new(heat_cap_fff_curve, 'Curve', 'Curve Result')
3904
+ heat_cap_fff_act.setName("#{obj_name} cap htg act")
3905
+
3906
+ heat_eir_fff_curve = heat_eir_fff_curves[speed]
3907
+ heat_eir_fff_act = OpenStudio::Model::EnergyManagementSystemActuator.new(heat_eir_fff_curve, 'Curve', 'Curve Result')
3908
+ heat_eir_fff_act.setName("#{obj_name} eir htg act")
3909
+
3910
+ fault_program.addLine("Set a1_AF_Qgr_h = #{heat_cap_fff_curve.coefficient1Constant}")
3911
+ fault_program.addLine("Set a2_AF_Qgr_h = #{heat_cap_fff_curve.coefficient2x}")
3912
+ fault_program.addLine("Set a3_AF_Qgr_h = #{heat_cap_fff_curve.coefficient3xPOW2}")
3913
+ fault_program.addLine("Set a1_AF_EIR_h = #{heat_eir_fff_curve.coefficient1Constant}")
3914
+ fault_program.addLine("Set a2_AF_EIR_h = #{heat_eir_fff_curve.coefficient2x}")
3915
+ fault_program.addLine("Set a3_AF_EIR_h = #{heat_eir_fff_curve.coefficient3xPOW2}")
3916
+
3917
+ qgr_values, p_values, ff_chg_values = get_installation_quality_heating_coeff(f_chg)
3918
+
3919
+ fault_program.addLine("Set a1_CH_Qgr_h = #{qgr_values[0]}")
3920
+ fault_program.addLine("Set a2_CH_Qgr_h = #{qgr_values[1]}")
3921
+ fault_program.addLine("Set a3_CH_Qgr_h = #{qgr_values[2]}")
3922
+
3923
+ fault_program.addLine("Set a1_CH_P_h = #{p_values[0]}")
3924
+ fault_program.addLine("Set a2_CH_P_h = #{p_values[1]}")
3925
+ fault_program.addLine("Set a3_CH_P_h = #{p_values[2]}")
3926
+
3927
+ ff_ch_h = 1 / (1 + (qgr_values[0] + qgr_values[1] * ff_chg_values[0] + qgr_values[2] * f_chg) * f_chg)
3928
+ fault_program.addLine("Set FF_CH_h = #{ff_ch_h.round(3)}")
3929
+
3930
+ fault_program.addLine('Set qh1_CH = a1_CH_Qgr_h')
3931
+ fault_program.addLine("Set qh2_CH = a2_CH_Qgr_h*#{tout_sensor.name}")
3932
+ fault_program.addLine('Set qh3_CH = a3_CH_Qgr_h*F_CH')
3933
+ fault_program.addLine('Set Y_CH_Q_h = 1 + ((qh1_CH+(qh2_CH)+(qh3_CH))*F_CH)')
3934
+
3935
+ fault_program.addLine('Set qh0_AF_CH = a1_AF_Qgr_h')
3936
+ fault_program.addLine('Set qh1_AF_CH = a2_AF_Qgr_h*FF_CH_h')
3937
+ fault_program.addLine('Set qh2_AF_CH = a3_AF_Qgr_h*FF_CH_h*FF_CH_h')
3938
+ fault_program.addLine('Set p_CH_Q_h = Y_CH_Q_h/(qh0_AF_CH + (qh1_AF_CH) +(qh2_AF_CH))')
3939
+
3940
+ fault_program.addLine('Set ph1_CH = a1_CH_P_h')
3941
+ fault_program.addLine("Set ph2_CH = a2_CH_P_h*#{tout_sensor.name}")
3942
+ fault_program.addLine('Set ph3_CH = a3_CH_P_h*F_CH')
3943
+ fault_program.addLine('Set Y_CH_COP_h = Y_CH_Q_h/(1 + ((ph1_CH+(ph2_CH)+(ph3_CH))*F_CH))')
3944
+
3945
+ fault_program.addLine('Set eirh0_AF_CH = a1_AF_EIR_h')
3946
+ fault_program.addLine('Set eirh1_AF_CH = a2_AF_EIR_h*FF_CH_h')
3947
+ fault_program.addLine('Set eirh2_AF_CH = a3_AF_EIR_h*FF_CH_h*FF_CH_h')
3948
+ fault_program.addLine('Set p_CH_COP_h = Y_CH_COP_h*(eirh0_AF_CH + (eirh1_AF_CH) + (eirh2_AF_CH))')
3949
+
3950
+ fault_program.addLine("Set FF_AF_h = 1.0 + #{heat_airflow_rated_defect_ratio[speed].round(3)}")
3951
+ fault_program.addLine('Set FF_AF_comb_h = FF_CH_h * FF_AF_h')
3952
+
3953
+ fault_program.addLine('Set qh0_AF_comb = a1_AF_Qgr_h')
3954
+ fault_program.addLine('Set qh1_AF_comb = a2_AF_Qgr_h*FF_AF_comb_h')
3955
+ fault_program.addLine('Set qh2_AF_comb = a3_AF_Qgr_h*FF_AF_comb_h*FF_AF_comb_h')
3956
+ fault_program.addLine('Set p_AF_Q_h = qh0_AF_comb+(qh1_AF_comb)+(qh2_AF_comb)')
3957
+
3958
+ fault_program.addLine('Set eirh0_AF_comb = a1_AF_EIR_h')
3959
+ fault_program.addLine('Set eirh1_AF_comb = a2_AF_EIR_h*FF_AF_comb_h')
3960
+ fault_program.addLine('Set eirh2_AF_comb = a3_AF_EIR_h*FF_AF_comb_h*FF_AF_comb_h')
3961
+ fault_program.addLine('Set p_AF_COP_h = 1.0/(eirh0_AF_comb+(eirh1_AF_comb)+(eirh2_AF_comb))')
3962
+
3963
+ fault_program.addLine("Set #{heat_cap_fff_act.name} = (p_CH_Q_h * p_AF_Q_h)")
3964
+ fault_program.addLine("Set #{heat_eir_fff_act.name} = 1.0 / (p_CH_COP_h * p_AF_COP_h)")
3965
+ end
3966
+ end
3967
+ program_calling_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
3968
+ program_calling_manager.setName("#{obj_name} program manager")
3969
+ program_calling_manager.setCallingPoint('BeginTimestepBeforePredictor')
3970
+ program_calling_manager.addProgram(fault_program)
3971
+ end
3972
+
4174
3973
  def self.get_default_gshp_pump_power()
4175
3974
  return 30.0 # W/ton, per ANSI/RESNET/ICC 301-2019 Section 4.4.5 (closed loop)
4176
3975
  end
4177
3976
 
4178
- def self.get_default_gshp_fan_power()
4179
- # Should this be 0.2 W/cfm per ANSI/RESNET/ICC 301-2019 Section 4.4.5? (or is 0.2 W/cfm
4180
- # interpreted as the _additional_ fan power beyond that captured in the rating test?)
4181
- return 0.5 # W/cfm
4182
- end
3977
+ def self.apply_shared_systems(hpxml = true)
3978
+ applied_clg = apply_shared_cooling_systems(hpxml)
3979
+ applied_htg = apply_shared_heating_systems(hpxml)
3980
+ return unless (applied_clg || applied_htg)
4183
3981
 
4184
- def self.apply_shared_systems(hpxml)
4185
- apply_shared_cooling_systems(hpxml)
4186
- apply_shared_heating_systems(hpxml)
4187
- HPXMLDefaults.apply_hvac(hpxml)
3982
+ # Remove WLHP if not serving heating nor cooling
3983
+ hpxml.heat_pumps.each do |hp|
3984
+ next unless hp.heat_pump_type == HPXML::HVACTypeHeatPumpWaterLoopToAir
3985
+ next if hp.fraction_heat_load_served > 0
3986
+ next if hp.fraction_cool_load_served > 0
3987
+
3988
+ hp.delete
3989
+ end
4188
3990
 
4189
3991
  # Remove any orphaned HVAC distributions
4190
3992
  hpxml.hvac_distributions.each do |hvac_distribution|
4191
3993
  hvac_systems = []
4192
- (hpxml.heating_systems + hpxml.cooling_systems + hpxml.heat_pumps).each do |hvac_system|
3994
+ hpxml.hvac_systems.each do |hvac_system|
4193
3995
  next if hvac_system.distribution_system_idref.nil?
4194
3996
  next unless hvac_system.distribution_system_idref == hvac_distribution.id
4195
3997
 
@@ -4202,12 +4004,14 @@ class HVAC
4202
4004
  end
4203
4005
 
4204
4006
  def self.apply_shared_cooling_systems(hpxml)
4007
+ applied = false
4205
4008
  hpxml.cooling_systems.each do |cooling_system|
4206
4009
  next unless cooling_system.is_shared_system
4207
4010
 
4011
+ applied = true
4012
+ wlhp = nil
4208
4013
  distribution_system = cooling_system.distribution_system
4209
4014
  distribution_type = distribution_system.distribution_system_type
4210
- hydronic_and_air_type = distribution_system.hydronic_and_air_type
4211
4015
 
4212
4016
  # Calculate air conditioner SEER equivalent
4213
4017
  n_dweq = cooling_system.number_of_units_served.to_f
@@ -4219,17 +4023,16 @@ class HVAC
4219
4023
  cap = cooling_system.cooling_capacity
4220
4024
  chiller_input = UnitConversions.convert(cooling_system.cooling_efficiency_kw_per_ton * UnitConversions.convert(cap, 'Btu/hr', 'ton'), 'kW', 'W')
4221
4025
  if distribution_type == HPXML::HVACDistributionTypeHydronic
4222
- aux_dweq = 0.0
4223
- elsif distribution_type == HPXML::HVACDistributionTypeHydronicAndAir
4224
- if hydronic_and_air_type == HPXML::HydronicAndAirTypeFanCoil
4225
- aux_dweq = cooling_system.fan_coil_watts
4226
- elsif hydronic_and_air_type == HPXML::HydronicAndAirTypeWaterLoopHeatPump
4227
- aux_dweq = cooling_system.wlhp_cooling_capacity / cooling_system.wlhp_cooling_efficiency_eer
4026
+ if distribution_system.hydronic_type == HPXML::HydronicTypeWaterLoop
4027
+ wlhp = hpxml.heat_pumps.select { |hp| hp.heat_pump_type == HPXML::HVACTypeHeatPumpWaterLoopToAir }[0]
4028
+ aux_dweq = wlhp.cooling_capacity / wlhp.cooling_efficiency_eer
4228
4029
  else
4229
- fail "Unexpected distribution type '#{hydronic_and_air_type}' for chiller."
4030
+ aux_dweq = 0.0
4031
+ end
4032
+ elsif distribution_type == HPXML::HVACDistributionTypeAir
4033
+ if distribution_system.air_type == HPXML::AirTypeFanCoil
4034
+ aux_dweq = cooling_system.fan_coil_watts
4230
4035
  end
4231
- else
4232
- fail "Unexpected distribution type '#{distribution_type}' for chiller."
4233
4036
  end
4234
4037
  # ANSI/RESNET/ICC 301-2019 Equation 4.4-2
4235
4038
  seer_eq = (cap - 3.41 * aux - 3.41 * aux_dweq * n_dweq) / (chiller_input + aux + aux_dweq * n_dweq)
@@ -4237,16 +4040,12 @@ class HVAC
4237
4040
  elsif cooling_system.cooling_system_type == HPXML::HVACTypeCoolingTower
4238
4041
 
4239
4042
  # Cooling tower w/ water loop heat pump
4240
- if distribution_type == HPXML::HVACDistributionTypeHydronicAndAir
4241
- hydronic_and_air_type = distribution_system.hydronic_and_air_type
4242
- if hydronic_and_air_type == HPXML::HydronicAndAirTypeWaterLoopHeatPump
4243
- wlhp_cap = cooling_system.wlhp_cooling_capacity
4244
- wlhp_input = wlhp_cap / cooling_system.wlhp_cooling_efficiency_eer
4245
- else
4246
- fail "Unexpected distribution type '#{hydronic_and_air_type}' for cooling tower."
4043
+ if distribution_type == HPXML::HVACDistributionTypeHydronic
4044
+ if distribution_system.hydronic_type == HPXML::HydronicTypeWaterLoop
4045
+ wlhp = hpxml.heat_pumps.select { |hp| hp.heat_pump_type == HPXML::HVACTypeHeatPumpWaterLoopToAir }[0]
4046
+ wlhp_cap = wlhp.cooling_capacity
4047
+ wlhp_input = wlhp_cap / wlhp.cooling_efficiency_eer
4247
4048
  end
4248
- else
4249
- fail "Unexpected hydronic distribution type '#{distribution_type}' for cooling tower."
4250
4049
  end
4251
4050
  # ANSI/RESNET/ICC 301-2019 Equation 4.4-3
4252
4051
  seer_eq = (wlhp_cap - 3.41 * aux / n_dweq) / (wlhp_input + aux / n_dweq)
@@ -4255,36 +4054,75 @@ class HVAC
4255
4054
  fail "Unexpected cooling system type '#{cooling_system.cooling_system_type}'."
4256
4055
  end
4257
4056
 
4057
+ if seer_eq <= 0
4058
+ fail "Negative SEER equivalent calculated for cooling system '#{cooling_system.id}', double check inputs."
4059
+ end
4060
+
4258
4061
  cooling_system.cooling_system_type = HPXML::HVACTypeCentralAirConditioner
4259
- cooling_system.cooling_efficiency_seer = seer_eq
4062
+ cooling_system.cooling_efficiency_seer = seer_eq.round(2)
4063
+ cooling_system.cooling_efficiency_kw_per_ton = nil
4260
4064
  cooling_system.cooling_capacity = nil # Autosize the equipment
4065
+ cooling_system.is_shared_system = false
4066
+ cooling_system.number_of_units_served = nil
4067
+ cooling_system.shared_loop_watts = nil
4068
+ cooling_system.shared_loop_motor_efficiency = nil
4069
+ cooling_system.fan_coil_watts = nil
4261
4070
 
4262
4071
  # Assign new distribution system to air conditioner
4263
4072
  if distribution_type == HPXML::HVACDistributionTypeHydronic
4264
- # Assign DSE=1
4265
- hpxml.hvac_distributions.add(id: "#{cooling_system.id}AirDistributionSystem",
4266
- distribution_system_type: HPXML::HVACDistributionTypeDSE,
4267
- annual_cooling_dse: 1)
4268
- cooling_system.distribution_system_idref = hpxml.hvac_distributions[-1].id
4269
- elsif distribution_type == HPXML::HVACDistributionTypeHydronicAndAir
4270
- # Assign AirDistribution
4271
- hpxml.hvac_distributions << distribution_system.dup
4272
- hpxml.hvac_distributions[-1].id = "#{cooling_system.id}AirDistributionSystem"
4273
- hpxml.hvac_distributions[-1].distribution_system_type = HPXML::HVACDistributionTypeAir
4274
- cooling_system.distribution_system_idref = hpxml.hvac_distributions[-1].id
4073
+ if distribution_system.hydronic_type == HPXML::HydronicTypeWaterLoop
4074
+ # Assign WLHP air distribution
4075
+ cooling_system.distribution_system_idref = wlhp.distribution_system_idref
4076
+ wlhp.fraction_cool_load_served = 0.0
4077
+ wlhp.fraction_heat_load_served = 0.0
4078
+ else
4079
+ # Assign DSE=1
4080
+ hpxml.hvac_distributions.add(id: "#{cooling_system.id}AirDistributionSystem",
4081
+ distribution_system_type: HPXML::HVACDistributionTypeDSE,
4082
+ annual_cooling_dse: 1.0,
4083
+ annual_heating_dse: 1.0)
4084
+ cooling_system.distribution_system_idref = hpxml.hvac_distributions[-1].id
4085
+ end
4086
+ elsif (distribution_type == HPXML::HVACDistributionTypeAir) && (distribution_system.air_type == HPXML::AirTypeFanCoil)
4087
+ # Convert "fan coil" air distribution system to "regular velocity"
4088
+ if distribution_system.hvac_systems.size > 1
4089
+ # Has attached heating system, so create a copy specifically for the cooling system
4090
+ hpxml.hvac_distributions << distribution_system.dup
4091
+ hpxml.hvac_distributions[-1].id += "#{cooling_system.id}AirDistributionSystem"
4092
+ cooling_system.distribution_system_idref = hpxml.hvac_distributions[-1].id
4093
+ end
4094
+ hpxml.hvac_distributions[-1].air_type = HPXML::AirTypeRegularVelocity
4095
+ if hpxml.hvac_distributions[-1].duct_leakage_measurements.select { |lm| (lm.duct_type == HPXML::DuctTypeSupply) && (lm.duct_leakage_total_or_to_outside == HPXML::DuctLeakageToOutside) }.size == 0
4096
+ # Assign zero supply leakage
4097
+ hpxml.hvac_distributions[-1].duct_leakage_measurements.add(duct_type: HPXML::DuctTypeSupply,
4098
+ duct_leakage_units: HPXML::UnitsCFM25,
4099
+ duct_leakage_value: 0,
4100
+ duct_leakage_total_or_to_outside: HPXML::DuctLeakageToOutside)
4101
+ end
4102
+ if hpxml.hvac_distributions[-1].duct_leakage_measurements.select { |lm| (lm.duct_type == HPXML::DuctTypeReturn) && (lm.duct_leakage_total_or_to_outside == HPXML::DuctLeakageToOutside) }.size == 0
4103
+ # Assign zero return leakage
4104
+ hpxml.hvac_distributions[-1].duct_leakage_measurements.add(duct_type: HPXML::DuctTypeReturn,
4105
+ duct_leakage_units: HPXML::UnitsCFM25,
4106
+ duct_leakage_value: 0,
4107
+ duct_leakage_total_or_to_outside: HPXML::DuctLeakageToOutside)
4108
+ end
4275
4109
  end
4276
4110
  end
4111
+
4112
+ return applied
4277
4113
  end
4278
4114
 
4279
4115
  def self.apply_shared_heating_systems(hpxml)
4116
+ applied = false
4280
4117
  hpxml.heating_systems.each do |heating_system|
4281
4118
  next unless heating_system.is_shared_system
4282
4119
 
4120
+ applied = true
4283
4121
  distribution_system = heating_system.distribution_system
4284
4122
  distribution_type = distribution_system.distribution_system_type
4285
- hydronic_and_air_type = distribution_system.hydronic_and_air_type
4123
+ hydronic_type = distribution_system.hydronic_type
4286
4124
 
4287
- if heating_system.heating_system_type == HPXML::HVACTypeBoiler && hydronic_and_air_type.to_s == HPXML::HydronicAndAirTypeWaterLoopHeatPump
4125
+ if heating_system.heating_system_type == HPXML::HVACTypeBoiler && hydronic_type.to_s == HPXML::HydronicTypeWaterLoop
4288
4126
 
4289
4127
  # Shared boiler w/ water loop heat pump
4290
4128
  # Per ANSI/RESNET/ICC 301-2019 Section 4.4.7.2, model as:
@@ -4293,24 +4131,125 @@ class HVAC
4293
4131
  fraction_heat_load_served = heating_system.fraction_heat_load_served
4294
4132
 
4295
4133
  # Heat pump
4296
- hpxml.heat_pumps.add(id: "#{heating_system.id}_WLHP",
4297
- distribution_system_idref: heating_system.distribution_system_idref,
4298
- heat_pump_type: HPXML::HVACTypeHeatPumpWaterLoopToAir,
4299
- heat_pump_fuel: HPXML::FuelTypeElectricity,
4300
- heating_efficiency_cop: heating_system.wlhp_heating_efficiency_cop,
4301
- fraction_heat_load_served: fraction_heat_load_served * (1.0 / heating_system.wlhp_heating_efficiency_cop),
4302
- fraction_cool_load_served: 0.0)
4134
+ # If this approach is ever removed, also remove code in HVACSizing.apply_hvac_loads()
4135
+ wlhp = hpxml.heat_pumps.select { |hp| hp.heat_pump_type == HPXML::HVACTypeHeatPumpWaterLoopToAir }[0]
4136
+ wlhp.fraction_heat_load_served = fraction_heat_load_served * (1.0 / wlhp.heating_efficiency_cop)
4137
+ wlhp.fraction_cool_load_served = 0.0
4303
4138
 
4304
4139
  # Boiler
4305
- heating_system.electric_auxiliary_energy = get_electric_auxiliary_energy(heating_system)
4306
- heating_system.fraction_heat_load_served = fraction_heat_load_served * (1.0 - 1.0 / heating_system.wlhp_heating_efficiency_cop)
4307
- heating_system.distribution_system_idref = "#{heating_system.id}_Baseboard"
4308
- hpxml.hvac_distributions.add(id: heating_system.distribution_system_idref,
4309
- distribution_system_type: HPXML::HVACDistributionTypeHydronic,
4310
- hydronic_type: HPXML::HydronicTypeBaseboard)
4140
+ heating_system.fraction_heat_load_served = fraction_heat_load_served * (1.0 - 1.0 / wlhp.heating_efficiency_cop)
4311
4141
  end
4312
4142
 
4313
4143
  heating_system.heating_capacity = nil # Autosize the equipment
4314
4144
  end
4145
+
4146
+ return applied
4147
+ end
4148
+
4149
+ def self.set_num_speeds(hvac_system)
4150
+ hvac_ap = hvac_system.additional_properties
4151
+
4152
+ if hvac_system.is_a?(HPXML::CoolingSystem) && (hvac_system.cooling_system_type == HPXML::HVACTypeRoomAirConditioner)
4153
+ hvac_ap.num_speeds = 1
4154
+ elsif (hvac_system.is_a?(HPXML::CoolingSystem) && (hvac_system.cooling_system_type == HPXML::HVACTypeMiniSplitAirConditioner)) ||
4155
+ (hvac_system.is_a?(HPXML::HeatPump) && (hvac_system.heat_pump_type == HPXML::HVACTypeHeatPumpMiniSplit))
4156
+ hvac_ap.speed_indices = [1, 3, 5, 9] # Speeds we model
4157
+ hvac_ap.num_speeds = hvac_ap.speed_indices.size
4158
+ elsif hvac_system.compressor_type == HPXML::HVACCompressorTypeSingleStage
4159
+ hvac_ap.num_speeds = 1
4160
+ elsif hvac_system.compressor_type == HPXML::HVACCompressorTypeTwoStage
4161
+ hvac_ap.num_speeds = 2
4162
+ elsif hvac_system.compressor_type == HPXML::HVACCompressorTypeVariableSpeed
4163
+ hvac_ap.num_speeds = 4
4164
+ end
4165
+ end
4166
+
4167
+ def self.calc_rated_airflow(capacity, rated_cfm_per_ton, capacity_ratio)
4168
+ return UnitConversions.convert(capacity, 'Btu/hr', 'ton') * UnitConversions.convert(rated_cfm_per_ton, 'cfm', 'm^3/s') * capacity_ratio
4169
+ end
4170
+
4171
+ def self.is_central_air_conditioner_and_furnace(hpxml, heating_system, cooling_system)
4172
+ if not (hpxml.heating_systems.include?(heating_system) && (heating_system.heating_system_type == HPXML::HVACTypeFurnace))
4173
+ return false
4174
+ end
4175
+ if not (hpxml.cooling_systems.include?(cooling_system) && (cooling_system.cooling_system_type == HPXML::HVACTypeCentralAirConditioner))
4176
+ return false
4177
+ end
4178
+
4179
+ return true
4180
+ end
4181
+
4182
+ def self.get_hpxml_hvac_systems(hpxml)
4183
+ # Returns a list of heating/cooling systems, incorporating whether
4184
+ # multiple systems are connected to the same distribution system
4185
+ # (e.g., a furnace + central air conditioner w/ the same ducts).
4186
+ hvac_systems = []
4187
+
4188
+ hpxml.cooling_systems.each do |cooling_system|
4189
+ heating_system = nil
4190
+ if is_central_air_conditioner_and_furnace(hpxml, cooling_system.attached_heating_system, cooling_system)
4191
+ heating_system = cooling_system.attached_heating_system
4192
+ end
4193
+ hvac_systems << { cooling: cooling_system,
4194
+ heating: heating_system }
4195
+ end
4196
+
4197
+ hpxml.heating_systems.each do |heating_system|
4198
+ if is_central_air_conditioner_and_furnace(hpxml, heating_system, heating_system.attached_cooling_system)
4199
+ next # Already processed combined AC+furnace
4200
+ end
4201
+ hvac_systems << { cooling: nil,
4202
+ heating: heating_system }
4203
+ end
4204
+
4205
+ hpxml.heat_pumps.each do |heat_pump|
4206
+ hvac_systems << { cooling: heat_pump,
4207
+ heating: heat_pump }
4208
+ end
4209
+
4210
+ return hvac_systems
4211
+ end
4212
+
4213
+ def self.ensure_nonzero_sizing_values(hpxml)
4214
+ min_capacity = 1.0 # Btuh
4215
+ min_airflow = 3.0 # cfm; E+ min airflow is 0.001 m3/s
4216
+ hpxml.heating_systems.each do |htg_sys|
4217
+ htg_sys.heating_capacity = [htg_sys.heating_capacity, min_capacity].max
4218
+ htg_sys.heating_airflow_cfm = [htg_sys.heating_airflow_cfm, min_airflow].max
4219
+ end
4220
+ hpxml.cooling_systems.each do |clg_sys|
4221
+ clg_sys.cooling_capacity = [clg_sys.cooling_capacity, min_capacity].max
4222
+ clg_sys.cooling_airflow_cfm = [clg_sys.cooling_airflow_cfm, min_airflow].max
4223
+ end
4224
+ hpxml.heat_pumps.each do |hp_sys|
4225
+ hp_sys.cooling_capacity = [hp_sys.cooling_capacity, min_capacity].max
4226
+ hp_sys.cooling_airflow_cfm = [hp_sys.cooling_airflow_cfm, min_airflow].max
4227
+ hp_sys.additional_properties.cooling_capacity_sensible = [hp_sys.additional_properties.cooling_capacity_sensible, min_capacity].max
4228
+ hp_sys.heating_capacity = [hp_sys.heating_capacity, min_capacity].max
4229
+ hp_sys.heating_airflow_cfm = [hp_sys.heating_airflow_cfm, min_airflow].max
4230
+ if not hp_sys.heating_capacity_17F.nil?
4231
+ hp_sys.heating_capacity_17F = [hp_sys.heating_capacity_17F, min_capacity].max
4232
+ end
4233
+ if not hp_sys.backup_heating_capacity.nil?
4234
+ hp_sys.backup_heating_capacity = [hp_sys.backup_heating_capacity, min_capacity].max
4235
+ end
4236
+ end
4237
+ end
4238
+
4239
+ def self.get_dehumidifier_default_values(capacity)
4240
+ rh_setpoint = 0.6
4241
+ if capacity <= 25.0
4242
+ ief = 0.79
4243
+ elsif capacity <= 35.0
4244
+ ief = 0.95
4245
+ elsif capacity <= 54.0
4246
+ ief = 1.04
4247
+ elsif capacity < 75.0
4248
+ ief = 1.20
4249
+ else
4250
+ ief = 1.82
4251
+ end
4252
+
4253
+ return { rh_setpoint: rh_setpoint, ief: ief }
4315
4254
  end
4316
4255
  end