urbanopt-cli 0.5.1 → 0.5.2

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