urbanopt-cli 0.4.1 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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