urbanopt-cli 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,64 +1,54 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class HVACSizing
4
- def self.apply(model, runner, weather, spaces, hpxml, infilvolume, nbeds, min_neighbor_distance, debug)
5
- @runner = runner
6
- @hpxml = hpxml
7
- @spaces = spaces
8
- @cond_zone = spaces[HPXML::LocationLivingSpace].thermalZone.get
9
-
10
- @conditioned_heat_design_temp = 70.0 # Indoor heating design temperature according to ACCA MANUAL J
11
- @conditioned_cool_design_temp = 75.0 # Indoor cooling design temperature according to ACCA MANUAL J
12
-
13
- @min_cooling_capacity = 1.0 # Btu/hr
14
-
15
- # Based on EnergyPlus's model for calculating SHR at off-rated conditions. This curve fit
16
- # avoids the iterations in the actual model. It does not account for altitude or variations
17
- # in the SHRRated. It is a function of ODB (MJ design temp) and CFM/Ton (from MJ)
18
- @shr_biquadratic = [1.08464364, 0.002096954, 0, -0.005766327, 0, -0.000011147]
4
+ def self.calculate(weather, hpxml, cfa, nbeds, hvac_systems)
5
+ # Calculates heating/cooling design loads, and selects equipment
6
+ # values (e.g., capacities, airflows) specific to each HVAC system.
7
+ # Calculations generally follow ACCA Manual J/S.
19
8
 
20
- # Inside air density
21
- @inside_air_dens = UnitConversions.convert(weather.header.LocalPressure, 'atm', 'Btu/ft^3') / (Gas.Air.r * (Constants.AssumedInsideTemp + 460.0))
9
+ @hpxml = hpxml
22
10
 
23
11
  process_site_calcs_and_design_temps(weather)
24
12
 
25
- # Get shelter class
26
- @shelter_class = get_shelter_class(model, min_neighbor_distance)
27
-
28
13
  # Calculate loads for the conditioned thermal zone
29
- zone_loads = process_zone_loads(model, weather, nbeds, infilvolume)
30
-
31
- # Display debug info
32
- display_zone_loads(zone_loads) if debug
14
+ bldg_design_loads = DesignLoads.new
15
+ process_load_windows_skylights(bldg_design_loads, weather)
16
+ process_load_doors(bldg_design_loads, weather)
17
+ process_load_walls(bldg_design_loads, weather)
18
+ process_load_roofs(bldg_design_loads, weather)
19
+ process_load_ceilings(bldg_design_loads, weather)
20
+ process_load_floors(bldg_design_loads, weather)
21
+ process_load_slabs(bldg_design_loads, weather)
22
+ process_load_infiltration_ventilation(bldg_design_loads, weather, cfa)
23
+ process_load_internal_gains(bldg_design_loads, nbeds)
33
24
 
34
25
  # Aggregate zone loads into initial loads
35
- init_loads = aggregate_zone_loads(zone_loads)
36
-
37
- # Get HVAC system info
38
- hvacs = get_hvacs(model)
26
+ aggregate_loads(bldg_design_loads)
39
27
 
40
- hvacs.each do |hvac|
41
- # Init
42
- hvac_init_loads = init_loads.dup
43
- calculate_hvac_temperatures(hvac_init_loads, hvac)
44
- apply_hvac_load_fractions(hvac_init_loads, hvac)
45
- apply_hp_sizing_logic(hvac_init_loads, hvac)
28
+ # Loop through each HVAC system
29
+ all_hvac_sizing_values = {}
30
+ hvac_systems.each do |hvac_system|
31
+ hvac = get_hvac_information(hvac_system)
46
32
 
47
- # Calculate final HVAC capacity/airflow
48
- hvac_final_values = FinalValues.new
49
- process_duct_loads_heating(hvac_final_values, weather, hvac, hvac_init_loads.Heat)
50
- process_duct_loads_cooling(hvac_final_values, weather, hvac, hvac_init_loads.Cool_Sens, hvac_init_loads.Cool_Lat)
51
- process_equipment_adjustments(hvac_final_values, weather, hvac)
52
- process_fixed_equipment(hvac_final_values, hvac)
53
- process_ground_loop(hvac_final_values, weather, hvac)
54
- process_finalize(hvac_final_values, zone_loads, weather, hvac)
33
+ # Add duct losses
34
+ apply_hvac_temperatures(hvac, bldg_design_loads)
35
+ apply_load_ducts_heating(bldg_design_loads, weather, hvac)
36
+ apply_load_ducts_cooling(bldg_design_loads, weather, hvac)
55
37
 
56
- # Set OpenStudio object values
57
- set_object_values(model, hvac, hvac_final_values)
38
+ # Calculate equipment values
39
+ hvac_sizing_values = HVACSizingValues.new
40
+ apply_hvac_loads(hvac, hvac_sizing_values, bldg_design_loads)
41
+ apply_hvac_heat_pump_logic(hvac_sizing_values, hvac)
42
+ apply_hvac_equipment_adjustments(hvac_sizing_values, weather, hvac, cfa)
43
+ apply_hvac_installation_quality(hvac_sizing_values, weather, hvac)
44
+ apply_hvac_fixed_capacities(hvac_sizing_values, hvac)
45
+ apply_hvac_ground_loop(hvac_sizing_values, weather, hvac)
46
+ apply_hvac_finalize_airflows(hvac_sizing_values, weather, hvac)
58
47
 
59
- # Display debug info
60
- display_hvac_final_values_results(hvac_final_values, hvac) if debug
48
+ all_hvac_sizing_values[hvac_system] = hvac_sizing_values
61
49
  end
50
+
51
+ return bldg_design_loads, all_hvac_sizing_values
62
52
  end
63
53
 
64
54
  private
@@ -72,8 +62,8 @@ class HVACSizing
72
62
  @daily_range_temp_adjust = [4, 0, -5]
73
63
 
74
64
  # Manual J inside conditions
75
- @cool_setpoint = 75
76
- @heat_setpoint = 70
65
+ @cool_setpoint = 75.0
66
+ @heat_setpoint = 70.0
77
67
 
78
68
  @cool_design_grains = UnitConversions.convert(weather.design.CoolingHumidityRatio, 'lbm/lbm', 'grains')
79
69
 
@@ -110,31 +100,49 @@ class HVACSizing
110
100
  @enthalpy_indoor_cooling = (1.006 * db_indoor_degC + hr_indoor_cooling * (2501.0 + 1.86 * db_indoor_degC)) * UnitConversions.convert(1.0, 'kJ', 'Btu') * UnitConversions.convert(1.0, 'lbm', 'kg')
111
101
  @wetbulb_outdoor_cooling = weather.design.CoolingWetbulb
112
102
 
103
+ # Inside air density
104
+ avg_setpoint = (@cool_setpoint + @heat_setpoint) / 2.0
105
+ @inside_air_dens = UnitConversions.convert(weather.header.LocalPressure, 'atm', 'Btu/ft^3') / (Gas.Air.r * (avg_setpoint + 460.0))
106
+
113
107
  # Design Temperatures
114
108
 
115
109
  @cool_design_temps = {}
116
110
  @heat_design_temps = {}
117
111
 
118
- @cool_design_temps[HPXML::LocationOutside] = weather.design.CoolingDrybulb
119
- @heat_design_temps[HPXML::LocationOutside] = weather.design.HeatingDrybulb
120
-
121
- [HPXML::LocationOtherHousingUnit, HPXML::LocationOtherHeatedSpace, HPXML::LocationOtherMultifamilyBufferSpace,
122
- HPXML::LocationOtherNonFreezingSpace, HPXML::LocationExteriorWall, HPXML::LocationUnderSlab].each do |space_type|
123
- @heat_design_temps[space_type] = calculate_scheduled_space_design_temps(space_type, @heat_setpoint, weather.design.HeatingDrybulb, weather.data.GroundMonthlyTemps.min)
124
- @cool_design_temps[space_type] = calculate_scheduled_space_design_temps(space_type, @cool_setpoint, weather.design.CoolingDrybulb, weather.data.GroundMonthlyTemps.max)
112
+ space_types = []
113
+ (@hpxml.roofs + @hpxml.rim_joists + @hpxml.walls + @hpxml.foundation_walls + @hpxml.frame_floors + @hpxml.slabs).each do |surface|
114
+ space_types << surface.interior_adjacent_to
115
+ space_types << surface.exterior_adjacent_to
116
+ end
117
+ @hpxml.hvac_distributions.each do |hvac_dist|
118
+ hvac_dist.ducts.each do |duct|
119
+ space_types << duct.duct_location
120
+ end
125
121
  end
126
122
 
127
- @spaces.each do |space_type, space|
128
- next unless space.is_a? OpenStudio::Model::Space
123
+ space_types.uniq.each do |space_type|
124
+ next if [HPXML::LocationGround].include? space_type
129
125
 
130
- @cool_design_temps[space_type] = process_design_temp_cooling(weather, space_type)
131
- @heat_design_temps[space_type] = process_design_temp_heating(weather, space_type)
126
+ if [HPXML::LocationOtherHousingUnit, HPXML::LocationOtherHeatedSpace, HPXML::LocationOtherMultifamilyBufferSpace,
127
+ HPXML::LocationOtherNonFreezingSpace, HPXML::LocationExteriorWall, HPXML::LocationUnderSlab].include? space_type
128
+ @cool_design_temps[space_type] = calculate_scheduled_space_design_temps(space_type, @cool_setpoint, weather.design.CoolingDrybulb, weather.data.GroundMonthlyTemps.max)
129
+ @heat_design_temps[space_type] = calculate_scheduled_space_design_temps(space_type, @heat_setpoint, weather.design.HeatingDrybulb, weather.data.GroundMonthlyTemps.min)
130
+ elsif [HPXML::LocationOutside, HPXML::LocationRoofDeck].include? space_type
131
+ @cool_design_temps[space_type] = weather.design.CoolingDrybulb
132
+ @heat_design_temps[space_type] = weather.design.HeatingDrybulb
133
+ elsif space_type == HPXML::LocationBasementConditioned
134
+ @cool_design_temps[space_type] = process_design_temp_cooling(weather, HPXML::LocationLivingSpace)
135
+ @heat_design_temps[space_type] = process_design_temp_heating(weather, HPXML::LocationLivingSpace)
136
+ else
137
+ @cool_design_temps[space_type] = process_design_temp_cooling(weather, space_type)
138
+ @heat_design_temps[space_type] = process_design_temp_heating(weather, space_type)
139
+ end
132
140
  end
133
141
  end
134
142
 
135
143
  def self.process_design_temp_heating(weather, space_type)
136
144
  if space_type == HPXML::LocationLivingSpace
137
- heat_temp = @conditioned_heat_design_temp
145
+ heat_temp = @heat_setpoint
138
146
 
139
147
  elsif space_type == HPXML::LocationGarage
140
148
  heat_temp = weather.design.HeatingDrybulb + 13.0
@@ -153,14 +161,14 @@ class HVACSizing
153
161
  if space_type == HPXML::LocationAtticVented
154
162
  heat_temp = weather.design.HeatingDrybulb
155
163
  else
156
- heat_temp = calculate_space_design_temps(space_type, weather, @conditioned_heat_design_temp, weather.design.HeatingDrybulb, weather.data.GroundMonthlyTemps.min)
164
+ heat_temp = calculate_space_design_temps(space_type, weather, @heat_setpoint, weather.design.HeatingDrybulb, weather.data.GroundMonthlyTemps.min)
157
165
  end
158
166
  else
159
167
  heat_temp = weather.design.HeatingDrybulb
160
168
  end
161
169
 
162
170
  elsif [HPXML::LocationBasementUnconditioned, HPXML::LocationCrawlspaceUnvented, HPXML::LocationCrawlspaceVented].include? space_type
163
- heat_temp = calculate_space_design_temps(space_type, weather, @conditioned_heat_design_temp, weather.design.HeatingDrybulb, weather.data.GroundMonthlyTemps.min)
171
+ heat_temp = calculate_space_design_temps(space_type, weather, @heat_setpoint, weather.design.HeatingDrybulb, weather.data.GroundMonthlyTemps.min)
164
172
 
165
173
  end
166
174
 
@@ -171,7 +179,7 @@ class HVACSizing
171
179
 
172
180
  def self.process_design_temp_cooling(weather, space_type)
173
181
  if space_type == HPXML::LocationLivingSpace
174
- cool_temp = @conditioned_cool_design_temp
182
+ cool_temp = @cool_setpoint
175
183
 
176
184
  elsif space_type == HPXML::LocationGarage
177
185
  # Calculate fraction of garage under conditioned space
@@ -188,7 +196,11 @@ class HVACSizing
188
196
  area_total += frame_floor.area
189
197
  area_conditioned += frame_floor.area if frame_floor.is_thermal_boundary
190
198
  end
191
- garage_frac_under_conditioned = area_conditioned / area_total
199
+ if area_total == 0
200
+ garage_frac_under_conditioned = 0.5
201
+ else
202
+ garage_frac_under_conditioned = area_conditioned / area_total
203
+ end
192
204
 
193
205
  # Calculate the garage cooling design temperature based on Table 4C
194
206
  # Linearly interpolate between having living space over the garage and not having living space above the garage
@@ -220,7 +232,7 @@ class HVACSizing
220
232
  if space_type == HPXML::LocationAtticVented
221
233
  cool_temp = weather.design.CoolingDrybulb + 40.0 # This is the number from a California study with dark shingle roof and similar ventilation.
222
234
  else
223
- cool_temp = calculate_space_design_temps(space_type, weather, @conditioned_cool_design_temp, weather.design.CoolingDrybulb, weather.data.GroundMonthlyTemps.max, true)
235
+ cool_temp = calculate_space_design_temps(space_type, weather, @cool_setpoint, weather.design.CoolingDrybulb, weather.data.GroundMonthlyTemps.max, true)
224
236
  end
225
237
 
226
238
  else
@@ -304,7 +316,7 @@ class HVACSizing
304
316
  end
305
317
 
306
318
  elsif [HPXML::LocationBasementUnconditioned, HPXML::LocationCrawlspaceUnvented, HPXML::LocationCrawlspaceVented].include? space_type
307
- cool_temp = calculate_space_design_temps(space_type, weather, @conditioned_cool_design_temp, weather.design.CoolingDrybulb, weather.data.GroundMonthlyTemps.max)
319
+ cool_temp = calculate_space_design_temps(space_type, weather, @cool_setpoint, weather.design.CoolingDrybulb, weather.data.GroundMonthlyTemps.max)
308
320
 
309
321
  end
310
322
 
@@ -313,20 +325,7 @@ class HVACSizing
313
325
  return cool_temp
314
326
  end
315
327
 
316
- def self.process_zone_loads(model, weather, nbeds, infilvolume)
317
- # Constant loads (no variation throughout day)
318
- zone_loads = ZoneLoads.new
319
- zone_loads = process_load_windows_skylights(zone_loads, weather)
320
- zone_loads = process_load_doors(zone_loads, weather)
321
- zone_loads = process_load_walls(zone_loads, weather)
322
- zone_loads = process_load_roofs(zone_loads, weather)
323
- zone_loads = process_load_floors(zone_loads, weather)
324
- zone_loads = process_infiltration_ventilation(model, zone_loads, weather, infilvolume)
325
- zone_loads = process_internal_gains(zone_loads, nbeds)
326
- return zone_loads
327
- end
328
-
329
- def self.process_load_windows_skylights(zone_loads, weather)
328
+ def self.process_load_windows_skylights(bldg_design_loads, weather)
330
329
  '''
331
330
  Heating and Cooling Loads: Windows & Skylights
332
331
  '''
@@ -436,13 +435,11 @@ class HVACSizing
436
435
  if latitude < 20.0
437
436
  psf_lat << psf[cnt][0]
438
437
  if cnt == 0
439
- @runner.registerWarning('Latitude of 20 was assumed for Manual J solar load calculations.')
440
438
  psf_lat_horiz = psf_horiz[0]
441
439
  end
442
440
  elsif latitude >= 64.0
443
441
  psf_lat << psf[cnt][11]
444
442
  if cnt == 0
445
- @runner.registerWarning('Latitude of 64 was assumed for Manual J solar load calculations.') if latitude > 64.0
446
443
  psf_lat_horiz = psf_horiz[11]
447
444
  end
448
445
  else
@@ -458,17 +455,18 @@ class HVACSizing
458
455
  end
459
456
 
460
457
  # Windows
461
- zone_loads.Heat_Windows = 0.0
458
+ bldg_design_loads.Heat_Windows = 0.0
462
459
  alp_load = 0.0 # Average Load Procedure (ALP) Load
463
460
  afl_hr = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] # Initialize Hourly Aggregate Fenestration Load (AFL)
464
461
 
465
462
  @hpxml.windows.each do |window|
466
463
  next unless window.wall.is_exterior_thermal_boundary
467
464
 
465
+ window_summer_sf = window.interior_shading_factor_summer * window.exterior_shading_factor_summer
468
466
  window_true_azimuth = get_true_azimuth(window.azimuth)
469
467
  cnt225 = (window_true_azimuth / 22.5).round.to_i
470
468
 
471
- zone_loads.Heat_Windows += window.ufactor * window.area * @htd
469
+ bldg_design_loads.Heat_Windows += window.ufactor * window.area * @htd
472
470
 
473
471
  for hr in -1..12
474
472
 
@@ -478,7 +476,7 @@ class HVACSizing
478
476
  # clf_d: Average Cooling Load Factor for the given window direction
479
477
  # clf_n: Average Cooling Load Factor for a window facing North (fully shaded)
480
478
  if hr == -1
481
- if window.interior_shading_factor_summer < 1
479
+ if window_summer_sf < 1
482
480
  clf_d = clf_avg_is[cnt225]
483
481
  clf_n = clf_avg_is[8]
484
482
  else
@@ -486,7 +484,7 @@ class HVACSizing
486
484
  clf_n = clf_avg_nois[8]
487
485
  end
488
486
  else
489
- if window.interior_shading_factor_summer < 1
487
+ if window_summer_sf < 1
490
488
  clf_d = clf_hr_is[cnt225][hr]
491
489
  clf_n = clf_hr_is[8][hr]
492
490
  else
@@ -502,10 +500,10 @@ class HVACSizing
502
500
  end
503
501
 
504
502
  # Hourly Heat Transfer Multiplier for the given window Direction
505
- htm_d = psf_lat[cnt225] * clf_d * window.shgc * window.interior_shading_factor_summer / 0.87 + window.ufactor * ctd_adj
503
+ htm_d = psf_lat[cnt225] * clf_d * window.shgc * window_summer_sf / 0.87 + window.ufactor * ctd_adj
506
504
 
507
505
  # Hourly Heat Transfer Multiplier for a window facing North (fully shaded)
508
- htm_n = psf_lat[8] * clf_n * window.shgc * window.interior_shading_factor_summer / 0.87 + window.ufactor * ctd_adj
506
+ htm_n = psf_lat[8] * clf_n * window.shgc * window_summer_sf / 0.87 + window.ufactor * ctd_adj
509
507
 
510
508
  if window_true_azimuth < 180
511
509
  surf_azimuth = window_true_azimuth
@@ -513,7 +511,7 @@ class HVACSizing
513
511
  surf_azimuth = window_true_azimuth - 360.0
514
512
  end
515
513
 
516
- if not window.overhangs_depth.nil?
514
+ if (not window.overhangs_depth.nil?) && (window.overhangs_depth > 0)
517
515
  if ((hr == -1) && (surf_azimuth.abs < 90.1)) || (hr > -1)
518
516
  if hr == -1
519
517
  actual_hr = slm_alp_hr[cnt225]
@@ -586,19 +584,20 @@ class HVACSizing
586
584
  eal = [0.0, pfl - ell].max
587
585
 
588
586
  # Window Cooling Load
589
- zone_loads.Cool_Windows = alp_load + eal
587
+ bldg_design_loads.Cool_Windows = alp_load + eal
590
588
 
591
589
  # Skylights
592
- zone_loads.Heat_Skylights = 0.0
590
+ bldg_design_loads.Heat_Skylights = 0.0
593
591
  alp_load = 0.0 # Average Load Procedure (ALP) Load
594
592
  afl_hr = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] # Initialize Hourly Aggregate Fenestration Load (AFL)
595
593
 
596
594
  @hpxml.skylights.each do |skylight|
595
+ skylight_summer_sf = skylight.interior_shading_factor_summer * skylight.exterior_shading_factor_summer
597
596
  skylight_true_azimuth = get_true_azimuth(skylight.azimuth)
598
597
  cnt225 = (skylight_true_azimuth / 22.5).round.to_i
599
598
  inclination_angle = UnitConversions.convert(Math.atan(skylight.roof.pitch / 12.0), 'rad', 'deg')
600
599
 
601
- zone_loads.Heat_Skylights += skylight.ufactor * skylight.area * @htd
600
+ bldg_design_loads.Heat_Skylights += skylight.ufactor * skylight.area * @htd
602
601
 
603
602
  for hr in -1..12
604
603
 
@@ -608,7 +607,7 @@ class HVACSizing
608
607
  # clf_d: Average Cooling Load Factor for the given skylight direction
609
608
  # clf_d: Average Cooling Load Factor for horizontal
610
609
  if hr == -1
611
- if skylight.interior_shading_factor_summer < 1
610
+ if skylight_summer_sf < 1
612
611
  clf_d = clf_avg_is[cnt225]
613
612
  clf_horiz = clf_avg_is_horiz
614
613
  else
@@ -616,7 +615,7 @@ class HVACSizing
616
615
  clf_horiz = clf_avg_nois_horiz
617
616
  end
618
617
  else
619
- if skylight.interior_shading_factor_summer < 1
618
+ if skylight_summer_sf < 1
620
619
  clf_d = clf_hr_is[cnt225][hr]
621
620
  clf_horiz = clf_hr_is_horiz[hr]
622
621
  else
@@ -638,7 +637,7 @@ class HVACSizing
638
637
  u_curb = 0.51 # default to wood (Table 2B-3)
639
638
  ar_curb = 0.35 # default to small (Table 2B-3)
640
639
  u_eff_skylight = skylight.ufactor + u_curb * ar_curb
641
- htm = (sol_h + sol_v) * (skylight.shgc * skylight.interior_shading_factor_summer / 0.87) + u_eff_skylight * (ctd_adj + 15.0)
640
+ htm = (sol_h + sol_v) * (skylight.shgc * skylight_summer_sf / 0.87) + u_eff_skylight * (ctd_adj + 15.0)
642
641
 
643
642
  if hr == -1
644
643
  alp_load += htm * skylight.area
@@ -661,12 +660,10 @@ class HVACSizing
661
660
  eal = [0.0, pfl - ell].max
662
661
 
663
662
  # Skylight Cooling Load
664
- zone_loads.Cool_Skylights = alp_load + eal
665
-
666
- return zone_loads
663
+ bldg_design_loads.Cool_Skylights = alp_load + eal
667
664
  end
668
665
 
669
- def self.process_load_doors(zone_loads, weather)
666
+ def self.process_load_doors(bldg_design_loads, weather)
670
667
  '''
671
668
  Heating and Cooling Loads: Doors
672
669
  '''
@@ -679,32 +676,30 @@ class HVACSizing
679
676
  cltd = @ctd + 6.0
680
677
  end
681
678
 
682
- zone_loads.Heat_Doors = 0.0
683
- zone_loads.Cool_Doors = 0.0
679
+ bldg_design_loads.Heat_Doors = 0.0
680
+ bldg_design_loads.Cool_Doors = 0.0
684
681
 
685
682
  @hpxml.doors.each do |door|
686
683
  next unless door.is_thermal_boundary
687
684
 
688
685
  if door.wall.is_exterior
689
- zone_loads.Heat_Doors += (1.0 / door.r_value) * door.area * @htd
690
- zone_loads.Cool_Doors += (1.0 / door.r_value) * door.area * cltd
691
- else
686
+ bldg_design_loads.Heat_Doors += (1.0 / door.r_value) * door.area * @htd
687
+ bldg_design_loads.Cool_Doors += (1.0 / door.r_value) * door.area * cltd
688
+ else # Partition door
692
689
  adjacent_space = door.wall.exterior_adjacent_to
693
- zone_loads.Cool_Doors += (1.0 / door.r_value) * door.area * (@cool_design_temps[adjacent_space] - @cool_setpoint)
694
- zone_loads.Heat_Doors += (1.0 / door.r_value) * door.area * (@heat_setpoint - @heat_design_temps[adjacent_space])
690
+ bldg_design_loads.Cool_Doors += (1.0 / door.r_value) * door.area * (@cool_design_temps[adjacent_space] - @cool_setpoint)
691
+ bldg_design_loads.Heat_Doors += (1.0 / door.r_value) * door.area * (@heat_setpoint - @heat_design_temps[adjacent_space])
695
692
  end
696
693
  end
697
-
698
- return zone_loads
699
694
  end
700
695
 
701
- def self.process_load_walls(zone_loads, weather)
696
+ def self.process_load_walls(bldg_design_loads, weather)
702
697
  '''
703
698
  Heating and Cooling Loads: Walls
704
699
  '''
705
700
 
706
- zone_loads.Heat_Walls = 0.0
707
- zone_loads.Cool_Walls = 0.0
701
+ bldg_design_loads.Heat_Walls = 0.0
702
+ bldg_design_loads.Cool_Walls = 0.0
708
703
 
709
704
  # Above-Grade Walls
710
705
  (@hpxml.walls + @hpxml.rim_joists).each do |wall|
@@ -762,12 +757,12 @@ class HVACSizing
762
757
  cltd = [cltd + cltd_corr, 0.0].max # Assume zero cooling load for negative CLTD's
763
758
  end
764
759
 
765
- zone_loads.Cool_Walls += (1.0 / wall.insulation_assembly_r_value) * wall_area / azimuths.size * cltd
766
- zone_loads.Heat_Walls += (1.0 / wall.insulation_assembly_r_value) * wall_area / azimuths.size * @htd
767
- else
760
+ bldg_design_loads.Cool_Walls += (1.0 / wall.insulation_assembly_r_value) * wall_area / azimuths.size * cltd
761
+ bldg_design_loads.Heat_Walls += (1.0 / wall.insulation_assembly_r_value) * wall_area / azimuths.size * @htd
762
+ else # Partition wall
768
763
  adjacent_space = wall.exterior_adjacent_to
769
- zone_loads.Cool_Walls += (1.0 / wall.insulation_assembly_r_value) * wall_area / azimuths.size * (@cool_design_temps[adjacent_space] - @cool_setpoint)
770
- zone_loads.Heat_Walls += (1.0 / wall.insulation_assembly_r_value) * wall_area / azimuths.size * (@heat_setpoint - @heat_design_temps[adjacent_space])
764
+ bldg_design_loads.Cool_Walls += (1.0 / wall.insulation_assembly_r_value) * wall_area / azimuths.size * (@cool_design_temps[adjacent_space] - @cool_setpoint)
765
+ bldg_design_loads.Heat_Walls += (1.0 / wall.insulation_assembly_r_value) * wall_area / azimuths.size * (@heat_setpoint - @heat_design_temps[adjacent_space])
771
766
  end
772
767
  end
773
768
  end
@@ -777,21 +772,17 @@ class HVACSizing
777
772
  next unless foundation_wall.is_exterior_thermal_boundary
778
773
 
779
774
  u_wall_with_soil, u_wall_without_soil = get_foundation_wall_properties(foundation_wall)
780
- zone_loads.Heat_Walls += u_wall_with_soil * foundation_wall.net_area * @htd
775
+ bldg_design_loads.Heat_Walls += u_wall_with_soil * foundation_wall.net_area * @htd
781
776
  end
782
-
783
- return zone_loads
784
777
  end
785
778
 
786
- def self.process_load_roofs(zone_loads, weather)
779
+ def self.process_load_roofs(bldg_design_loads, weather)
787
780
  '''
788
- Heating and Cooling Loads: Ceilings
781
+ Heating and Cooling Loads: Roofs
789
782
  '''
790
783
 
791
- cltd = 0.0
792
-
793
- zone_loads.Heat_Roofs = 0.0
794
- zone_loads.Cool_Roofs = 0.0
784
+ bldg_design_loads.Heat_Roofs = 0.0
785
+ bldg_design_loads.Cool_Roofs = 0.0
795
786
 
796
787
  # Roofs
797
788
  @hpxml.roofs.each do |roof|
@@ -834,40 +825,108 @@ class HVACSizing
834
825
  # Adjust base CLTD for different CTD or DR
835
826
  cltd += (weather.design.CoolingDrybulb - 95.0) + @daily_range_temp_adjust[@daily_range_num]
836
827
 
837
- zone_loads.Cool_Roofs += (1.0 / roof.insulation_assembly_r_value) * roof.net_area * cltd
838
- zone_loads.Heat_Roofs += (1.0 / roof.insulation_assembly_r_value) * roof.net_area * @htd
828
+ bldg_design_loads.Cool_Roofs += (1.0 / roof.insulation_assembly_r_value) * roof.net_area * cltd
829
+ bldg_design_loads.Heat_Roofs += (1.0 / roof.insulation_assembly_r_value) * roof.net_area * @htd
839
830
  end
831
+ end
832
+
833
+ def self.process_load_ceilings(bldg_design_loads, weather)
834
+ '''
835
+ Heating and Cooling Loads: Ceilings
836
+ '''
840
837
 
841
- return zone_loads
838
+ bldg_design_loads.Heat_Ceilings = 0.0
839
+ bldg_design_loads.Cool_Ceilings = 0.0
840
+
841
+ @hpxml.frame_floors.each do |frame_floor|
842
+ next unless frame_floor.is_ceiling
843
+ next unless frame_floor.is_thermal_boundary
844
+
845
+ if frame_floor.is_exterior
846
+ bldg_design_loads.Cool_Ceilings += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * (@ctd - 5.0 + @daily_range_temp_adjust[@daily_range_num])
847
+ bldg_design_loads.Heat_Ceilings += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * @htd
848
+ else
849
+ adjacent_space = frame_floor.exterior_adjacent_to
850
+ bldg_design_loads.Cool_Ceilings += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * (@cool_design_temps[adjacent_space] - @cool_setpoint)
851
+ bldg_design_loads.Heat_Ceilings += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * (@heat_setpoint - @heat_design_temps[adjacent_space])
852
+ end
853
+ end
842
854
  end
843
855
 
844
- def self.process_load_floors(zone_loads, weather)
856
+ def self.process_load_floors(bldg_design_loads, weather)
845
857
  '''
846
858
  Heating and Cooling Loads: Floors
847
859
  '''
848
860
 
849
- zone_loads.Heat_Floors = 0.0
850
- zone_loads.Cool_Floors = 0.0
861
+ bldg_design_loads.Heat_Floors = 0.0
862
+ bldg_design_loads.Cool_Floors = 0.0
851
863
 
852
864
  @hpxml.frame_floors.each do |frame_floor|
865
+ next unless frame_floor.is_floor
853
866
  next unless frame_floor.is_thermal_boundary
854
867
 
855
868
  if frame_floor.is_exterior
856
- zone_loads.Cool_Floors += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * (@ctd - 5.0 + @daily_range_temp_adjust[@daily_range_num])
857
- zone_loads.Heat_Floors += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * @htd
858
- else
869
+ bldg_design_loads.Cool_Floors += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * (@ctd - 5.0 + @daily_range_temp_adjust[@daily_range_num])
870
+ bldg_design_loads.Heat_Floors += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * @htd
871
+ else # Partition floor
859
872
  adjacent_space = frame_floor.exterior_adjacent_to
860
- zone_loads.Cool_Floors += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * (@cool_design_temps[adjacent_space] - @cool_setpoint)
861
- zone_loads.Heat_Floors += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * (@heat_setpoint - @heat_design_temps[adjacent_space])
873
+ if frame_floor.is_floor && [HPXML::LocationCrawlspaceVented, HPXML::LocationCrawlspaceUnvented, HPXML::LocationBasementUnconditioned].include?(adjacent_space)
874
+ u_floor = 1.0 / frame_floor.insulation_assembly_r_value
875
+
876
+ sum_ua_wall = 0.0
877
+ sum_a_wall = 0.0
878
+ @hpxml.foundation_walls.each do |foundation_wall|
879
+ next unless foundation_wall.is_exterior && foundation_wall.interior_adjacent_to == adjacent_space
880
+
881
+ u_wall_with_soil, u_wall_without_soil = get_foundation_wall_properties(foundation_wall)
882
+
883
+ sum_a_wall += foundation_wall.net_area
884
+ sum_ua_wall += (u_wall_without_soil * foundation_wall.net_area)
885
+ end
886
+ @hpxml.walls.each do |wall|
887
+ next unless wall.is_exterior && wall.interior_adjacent_to == adjacent_space
888
+
889
+ sum_a_wall += wall.net_area
890
+ sum_ua_wall += (1.0 / wall.insulation_assembly_r_value * wall.net_area)
891
+ end
892
+ fail 'Could not find connected walls.' if sum_a_wall <= 0
893
+ u_wall = sum_ua_wall / sum_a_wall
894
+
895
+ # Calculate partition temperature different cooling (PTDC) per Manual J Figure A12-17
896
+ # Calculate partition temperature different heating (PTDH) per Manual J Figure A12-6
897
+ if [HPXML::LocationCrawlspaceVented].include? adjacent_space
898
+ # Vented or Leaky
899
+ ptdc_floor = @ctd / (1.0 + (4.0 * u_floor) / (u_wall + 0.11))
900
+ ptdh_floor = @htd / (1.0 + (4.0 * u_floor) / (u_wall + 0.11))
901
+ elsif [HPXML::LocationCrawlspaceUnvented, HPXML::LocationBasementUnconditioned].include? adjacent_space
902
+ # Sealed Tight
903
+ ptdc_floor = u_wall * @ctd / (4.0 * u_floor + u_wall)
904
+ ptdh_floor = u_wall * @htd / (4.0 * u_floor + u_wall)
905
+ end
906
+
907
+ bldg_design_loads.Cool_Floors += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * ptdc_floor
908
+ bldg_design_loads.Heat_Floors += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * ptdh_floor
909
+ else # E.g., floor over garage
910
+ bldg_design_loads.Cool_Floors += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * (@cool_design_temps[adjacent_space] - @cool_setpoint)
911
+ bldg_design_loads.Heat_Floors += (1.0 / frame_floor.insulation_assembly_r_value) * frame_floor.area * (@heat_setpoint - @heat_design_temps[adjacent_space])
912
+ end
862
913
  end
863
914
  end
915
+ end
916
+
917
+ def self.process_load_slabs(bldg_design_loads, weather)
918
+ '''
919
+ Heating and Cooling Loads: Floors
920
+ '''
921
+
922
+ bldg_design_loads.Heat_Slabs = 0.0
864
923
 
865
924
  @hpxml.slabs.each do |slab|
866
925
  next unless slab.is_thermal_boundary
867
926
 
868
927
  if slab.interior_adjacent_to == HPXML::LocationLivingSpace # Slab-on-grade
869
928
  f_value = calc_slab_f_value(slab)
870
- zone_loads.Heat_Floors += f_value * slab.exposed_perimeter * @htd
929
+ bldg_design_loads.Heat_Slabs += f_value * slab.exposed_perimeter * @htd
871
930
  elsif slab.interior_adjacent_to == HPXML::LocationBasementConditioned
872
931
  # Based on MJ 8th Ed. A12-7 and ASHRAE HoF 2013 pg 18.31 Eq 40
873
932
  # FIXME: Assumes slab is uninsulated?
@@ -879,95 +938,120 @@ class HVACSizing
879
938
  length = slab.exposed_perimeter / 4.0 + Math.sqrt(sqrt_term) / 4.0
880
939
  width = slab.exposed_perimeter / 4.0 - Math.sqrt(sqrt_term) / 4.0
881
940
  w_b = [length, width].min
941
+ w_b = [w_b, 1.0].max # handle zero exposed perimeter
882
942
  u_avg_bf = (2.0 * k_soil / (Math::PI * w_b)) * (Math::log(w_b / 2.0 + z_f / 2.0 + (k_soil * r_other) / Math::PI) - Math::log(z_f / 2.0 + (k_soil * r_other) / Math::PI))
883
943
  u_value_mj8 = 0.85 * u_avg_bf
884
- zone_loads.Heat_Floors += u_value_mj8 * slab.area * @htd
944
+ bldg_design_loads.Heat_Slabs += u_value_mj8 * slab.area * @htd
885
945
  end
886
946
  end
887
-
888
- return zone_loads
889
947
  end
890
948
 
891
- def self.process_infiltration_ventilation(model, zone_loads, weather, infilvolume)
949
+ def self.process_load_infiltration_ventilation(bldg_design_loads, weather, cfa)
892
950
  '''
893
951
  Heating and Cooling Loads: Infiltration & Ventilation
894
952
  '''
895
953
 
896
- # Per ANSI/RESNET/ICC 301
897
- ach_nat = get_feature(@cond_zone, Constants.SizingInfoZoneInfiltrationACH, 'double')
954
+ # FUTURE: Consolidate code w/ airflow.rb
955
+ infil_volume = @hpxml.air_infiltration_measurements.select { |i| !i.infiltration_volume.nil? }[0].infiltration_volume
956
+ infil_height = @hpxml.inferred_infiltration_height(infil_volume)
957
+ sla = nil
958
+ @hpxml.air_infiltration_measurements.each do |measurement|
959
+ if [HPXML::UnitsACH, HPXML::UnitsCFM].include?(measurement.unit_of_measure) && !measurement.house_pressure.nil?
960
+ if measurement.unit_of_measure == HPXML::UnitsACH
961
+ ach50 = Airflow.calc_air_leakage_at_diff_pressure(0.65, measurement.air_leakage, measurement.house_pressure, 50.0)
962
+ elsif measurement.unit_of_measure == HPXML::UnitsCFM
963
+ achXX = measurement.air_leakage * 60.0 / infil_volume # Convert CFM to ACH
964
+ ach50 = Airflow.calc_air_leakage_at_diff_pressure(0.65, achXX, measurement.house_pressure, 50.0)
965
+ end
966
+ sla = Airflow.get_infiltration_SLA_from_ACH50(ach50, 0.65, cfa, infil_volume)
967
+ elsif measurement.unit_of_measure == HPXML::UnitsACHNatural
968
+ sla = Airflow.get_infiltration_SLA_from_ACH(measurement.air_leakage, infil_height, weather)
969
+ end
970
+ end
971
+ ela = sla * cfa
972
+
973
+ ncfl_ag = @hpxml.building_construction.number_of_conditioned_floors_above_grade
898
974
 
899
- ach_Cooling = 1.2 * ach_nat
900
- ach_Heating = 1.6 * ach_nat
975
+ # Set stack/wind coefficients from Tables 5D/5E
976
+ c_s = 0.015 * ncfl_ag
977
+ c_w_base = [0.0133 * @hpxml.site.additional_properties.aim2_shelter_coeff - 0.0027, 0.0].max # Linear relationship between shelter coefficient and c_w coefficients by shielding class
978
+ c_w = c_w_base * ncfl_ag**0.4
901
979
 
902
- icfm_Cooling = ach_Cooling / UnitConversions.convert(1.0, 'hr', 'min') * infilvolume
903
- icfm_Heating = ach_Heating / UnitConversions.convert(1.0, 'hr', 'min') * infilvolume
980
+ ela_in2 = UnitConversions.convert(ela, 'ft^2', 'in^2')
981
+ windspeed_cooling_mph = 7.5 # Table 5D/5E Wind Velocity Value footnote
982
+ windspeed_heating_mph = 15.0 # Table 5D/5E Wind Velocity Value footnote
904
983
 
905
- q_unb_cfm, q_preheat, q_precool, q_recirc, q_bal_Sens, q_bal_Lat = get_ventilation_rates(model)
984
+ icfm_Cooling = ela_in2 * (c_s * @ctd + c_w * windspeed_cooling_mph**2)**0.5
985
+ icfm_Heating = ela_in2 * (c_s * @htd + c_w * windspeed_heating_mph**2)**0.5
986
+
987
+ q_unb_cfm, q_preheat, q_precool, q_recirc, q_bal_Sens, q_bal_Lat = get_ventilation_rates()
906
988
 
907
989
  cfm_Heating = q_bal_Sens + (icfm_Heating**2.0 + q_unb_cfm**2.0)**0.5 - q_preheat - q_recirc
908
990
 
909
991
  cfm_Cool_Load_Sens = q_bal_Sens + (icfm_Cooling**2.0 + q_unb_cfm**2.0)**0.5 - q_precool - q_recirc
910
992
  cfm_Cool_Load_Lat = q_bal_Lat + (icfm_Cooling**2.0 + q_unb_cfm**2.0)**0.5 - q_recirc
911
993
 
912
- zone_loads.Heat_Infil = 1.1 * @acf * cfm_Heating * @htd
913
-
914
- zone_loads.Cool_Infil_Sens = 1.1 * @acf * cfm_Cool_Load_Sens * @ctd
915
- zone_loads.Cool_Infil_Lat = 0.68 * @acf * cfm_Cool_Load_Lat * (@cool_design_grains - @cool_indoor_grains)
994
+ bldg_design_loads.Heat_InfilVent = 1.1 * @acf * cfm_Heating * @htd
916
995
 
917
- return zone_loads
996
+ bldg_design_loads.Cool_Infil_Sens = 1.1 * @acf * cfm_Cool_Load_Sens * @ctd
997
+ bldg_design_loads.Cool_Infil_Lat = 0.68 * @acf * cfm_Cool_Load_Lat * (@cool_design_grains - @cool_indoor_grains)
918
998
  end
919
999
 
920
- def self.process_internal_gains(zone_loads, nbeds)
1000
+ def self.process_load_internal_gains(bldg_design_loads, nbeds)
921
1001
  '''
922
1002
  Cooling Load: Internal Gains
923
1003
  '''
924
1004
 
925
1005
  # Per ANSI/RESNET/ICC 301
926
1006
  n_occupants = nbeds + 1
927
- zone_loads.Cool_IntGains_Sens = 1600.0 + 230.0 * n_occupants
928
- zone_loads.Cool_IntGains_Lat = 200.0 * n_occupants
929
-
930
- return zone_loads
1007
+ bldg_design_loads.Cool_IntGains_Sens = 1600.0 + 230.0 * n_occupants
1008
+ bldg_design_loads.Cool_IntGains_Lat = 200.0 * n_occupants
931
1009
  end
932
1010
 
933
- def self.aggregate_zone_loads(zone_loads)
1011
+ def self.aggregate_loads(bldg_design_loads)
934
1012
  '''
935
- Intermediate Loads
936
- (total loads excluding ducts)
1013
+ Building Loads (excluding ducts)
937
1014
  '''
938
1015
 
939
- init_loads = InitialLoads.new
940
1016
  # Heating
941
- init_loads.Heat = [zone_loads.Heat_Windows + zone_loads.Heat_Skylights +
942
- zone_loads.Heat_Doors + zone_loads.Heat_Walls +
943
- zone_loads.Heat_Floors + zone_loads.Heat_Roofs, 0.0].max +
944
- zone_loads.Heat_Infil
1017
+ bldg_design_loads.Heat_Tot = [bldg_design_loads.Heat_Windows + bldg_design_loads.Heat_Skylights +
1018
+ bldg_design_loads.Heat_Doors + bldg_design_loads.Heat_Walls +
1019
+ bldg_design_loads.Heat_Floors + bldg_design_loads.Heat_Slabs +
1020
+ bldg_design_loads.Heat_Ceilings + bldg_design_loads.Heat_Roofs, 0.0].max +
1021
+ bldg_design_loads.Heat_InfilVent
945
1022
 
946
1023
  # Cooling
947
- init_loads.Cool_Sens = zone_loads.Cool_Windows + zone_loads.Cool_Skylights +
948
- zone_loads.Cool_Doors + zone_loads.Cool_Walls +
949
- zone_loads.Cool_Floors + zone_loads.Cool_Roofs +
950
- zone_loads.Cool_Infil_Sens + zone_loads.Cool_IntGains_Sens
951
- init_loads.Cool_Lat = zone_loads.Cool_Infil_Lat + zone_loads.Cool_IntGains_Lat
952
-
953
- init_loads.Cool_Lat = [init_loads.Cool_Lat, 0.0].max
954
- init_loads.Cool_Tot = init_loads.Cool_Sens + init_loads.Cool_Lat
955
-
956
- return init_loads
957
- end
958
-
959
- def self.calculate_hvac_temperatures(hvac_init_loads, hvac)
1024
+ bldg_design_loads.Cool_Sens = bldg_design_loads.Cool_Windows + bldg_design_loads.Cool_Skylights +
1025
+ bldg_design_loads.Cool_Doors + bldg_design_loads.Cool_Walls +
1026
+ bldg_design_loads.Cool_Floors + bldg_design_loads.Cool_Ceilings +
1027
+ bldg_design_loads.Cool_Roofs + bldg_design_loads.Cool_Infil_Sens +
1028
+ bldg_design_loads.Cool_IntGains_Sens
1029
+ bldg_design_loads.Cool_Lat = bldg_design_loads.Cool_Infil_Lat + bldg_design_loads.Cool_IntGains_Lat
1030
+ if bldg_design_loads.Cool_Lat < 0 # No latent loads; also zero out individual components
1031
+ bldg_design_loads.Cool_Lat = 0.0
1032
+ bldg_design_loads.Cool_Infil_Lat = 0.0
1033
+ bldg_design_loads.Cool_IntGains_Lat = 0.0
1034
+ end
1035
+ bldg_design_loads.Cool_Tot = bldg_design_loads.Cool_Sens + bldg_design_loads.Cool_Lat
1036
+
1037
+ # Initialize ducts
1038
+ bldg_design_loads.Heat_Ducts = 0.0
1039
+ bldg_design_loads.Cool_Ducts_Sens = 0.0
1040
+ bldg_design_loads.Cool_Ducts_Lat = 0.0
1041
+ end
1042
+
1043
+ def self.apply_hvac_temperatures(hvac, bldg_design_loads)
960
1044
  '''
961
1045
  HVAC Temperatures
962
1046
  '''
963
- # evap cooler temperature calculation based on Mannual S Figure 4-7
964
- if hvac.has_type(Constants.ObjectNameEvaporativeCooler)
1047
+ # Evaporative cooler temperature calculation based on Manual S Figure 4-7
1048
+ if hvac.CoolType == HPXML::HVACTypeEvaporativeCooler
965
1049
  td_potential = @cool_design_temps[HPXML::LocationOutside] - @wetbulb_outdoor_cooling
966
1050
  td = td_potential * hvac.EvapCoolerEffectiveness
967
1051
  hvac.LeavingAirTemp = @cool_design_temps[HPXML::LocationOutside] - td
968
1052
  else
969
1053
  # Calculate Leaving Air Temperature
970
- shr = [hvac_init_loads.Cool_Sens / hvac_init_loads.Cool_Tot, 1.0].min
1054
+ shr = [bldg_design_loads.Cool_Sens / bldg_design_loads.Cool_Tot, 1.0].min
971
1055
  # Determine the Leaving Air Temperature (LAT) based on Manual S Table 1-4
972
1056
  if shr < 0.80
973
1057
  hvac.LeavingAirTemp = 54.0 # F
@@ -981,42 +1065,46 @@ class HVACSizing
981
1065
  end
982
1066
 
983
1067
  # Calculate Supply Air Temperature
984
- if hvac.has_type(Constants.ObjectNameFurnace)
985
- hvac.SupplyAirTemp = 120.0 # F
986
- else
1068
+ if [HPXML::HVACTypeHeatPumpAirToAir,
1069
+ HPXML::HVACTypeHeatPumpMiniSplit,
1070
+ HPXML::HVACTypeHeatPumpGroundToAir,
1071
+ HPXML::HVACTypeHeatPumpWaterLoopToAir].include? hvac.HeatType
987
1072
  hvac.SupplyAirTemp = 105.0 # F
1073
+ else
1074
+ hvac.SupplyAirTemp = 120.0 # F
988
1075
  end
989
1076
  end
990
1077
 
991
- def self.apply_hvac_load_fractions(hvac_init_loads, hvac)
992
- '''
993
- Intermediate Loads (HVAC-specific)
994
- '''
995
- hvac_init_loads.Heat *= hvac.HeatingLoadFraction
996
- hvac_init_loads.Cool_Sens *= hvac.CoolingLoadFraction
997
- hvac_init_loads.Cool_Lat *= hvac.CoolingLoadFraction
998
- hvac_init_loads.Cool_Tot *= hvac.CoolingLoadFraction
1078
+ def self.apply_hvac_loads(hvac, hvac_sizing_values, bldg_design_loads)
1079
+ # Calculate design loads that this HVAC system serves
999
1080
 
1000
- # Prevent error for, e.g., an ASHP with CoolingLoadFraction == 0.
1001
- hvac_init_loads.Heat = [hvac_init_loads.Heat, 0.001].max
1002
- hvac_init_loads.Cool_Sens = [hvac_init_loads.Cool_Sens, 0.001].max
1003
- hvac_init_loads.Cool_Lat = [hvac_init_loads.Cool_Lat, 0.001].max
1004
- hvac_init_loads.Cool_Tot = [hvac_init_loads.Cool_Tot, 0.001].max
1081
+ # Heating
1082
+ hvac_sizing_values.Heat_Load = bldg_design_loads.Heat_Tot * hvac.HeatingLoadFraction
1083
+ if hvac.HeatType == HPXML::HVACTypeHeatPumpWaterLoopToAir
1084
+ # Size to meet original fraction load served (not adjusted value from HVAC.apply_shared_heating_systems()
1085
+ # This ensures, e.g., that an appropriate heating airflow is used for duct losses.
1086
+ hvac_sizing_values.Heat_Load = hvac_sizing_values.Heat_Load / (1.0 / hvac.HeatingCOP)
1087
+ end
1088
+
1089
+ # Cooling
1090
+ hvac_sizing_values.Cool_Load_Tot = bldg_design_loads.Cool_Tot * hvac.CoolingLoadFraction
1091
+ hvac_sizing_values.Cool_Load_Sens = bldg_design_loads.Cool_Sens * hvac.CoolingLoadFraction
1092
+ hvac_sizing_values.Cool_Load_Lat = bldg_design_loads.Cool_Lat * hvac.CoolingLoadFraction
1005
1093
  end
1006
1094
 
1007
- def self.apply_hp_sizing_logic(hvac_init_loads, hvac)
1095
+ def self.apply_hvac_heat_pump_logic(hvac_sizing_values, hvac)
1008
1096
  # If true, uses the larger of heating and cooling loads for heat pump capacity sizing (required for ERI).
1009
1097
  # Otherwise, uses standard Manual S oversize allowances.
1010
- if hvac.has_type([Constants.ObjectNameAirSourceHeatPump,
1011
- Constants.ObjectNameMiniSplitHeatPump,
1012
- Constants.ObjectNameGroundSourceHeatPump,
1013
- Constants.ObjectNameWaterLoopHeatPump])
1014
- if @hpxml.header.use_max_load_for_heat_pumps
1015
- max_load = [hvac_init_loads.Heat, hvac_init_loads.Cool_Tot].max
1016
- hvac_init_loads.Heat = max_load
1017
- hvac_init_loads.Cool_Sens *= max_load / hvac_init_loads.Cool_Tot
1018
- hvac_init_loads.Cool_Lat *= max_load / hvac_init_loads.Cool_Tot
1019
- hvac_init_loads.Cool_Tot = max_load
1098
+ if [HPXML::HVACTypeHeatPumpAirToAir,
1099
+ HPXML::HVACTypeHeatPumpMiniSplit,
1100
+ HPXML::HVACTypeHeatPumpGroundToAir,
1101
+ HPXML::HVACTypeHeatPumpWaterLoopToAir].include? hvac.CoolType
1102
+ if @hpxml.header.use_max_load_for_heat_pumps && (hvac.CoolingLoadFraction > 0) && (hvac.HeatingLoadFraction > 0)
1103
+ max_load = [hvac_sizing_values.Heat_Load, hvac_sizing_values.Cool_Load_Tot].max
1104
+ hvac_sizing_values.Heat_Load = max_load
1105
+ hvac_sizing_values.Cool_Load_Sens *= max_load / hvac_sizing_values.Cool_Load_Tot
1106
+ hvac_sizing_values.Cool_Load_Lat *= max_load / hvac_sizing_values.Cool_Load_Tot
1107
+ hvac_sizing_values.Cool_Load_Tot = max_load
1020
1108
 
1021
1109
  # Override Manual S oversize allowances:
1022
1110
  hvac.OverSizeLimit = 1.0
@@ -1095,137 +1183,129 @@ class HVACSizing
1095
1183
  return dse_Fregain
1096
1184
  end
1097
1185
 
1098
- def self.process_duct_loads_heating(hvac_final_values, weather, hvac, init_heat_load)
1186
+ def self.apply_load_ducts_heating(bldg_design_loads, weather, hvac)
1099
1187
  '''
1100
1188
  Heating Duct Loads
1101
1189
  '''
1102
- if (init_heat_load == 0) || (hvac.Ducts.size == 0)
1103
- hvac_final_values.Heat_Load_Ducts = 0.0
1104
- hvac_final_values.Heat_Load = init_heat_load
1105
- else
1106
- # Distribution system efficiency (DSE) calculations based on ASHRAE Standard 152
1107
- dse_As, dse_Ar = calc_ducts_areas(hvac.Ducts)
1108
- supply_r, return_r = calc_ducts_rvalues(hvac.Ducts)
1109
1190
 
1110
- design_temp_values = { HPXML::DuctTypeSupply => @heat_design_temps, HPXML::DuctTypeReturn => @heat_design_temps }
1111
- dse_Tamb_heating_s, dse_Tamb_heating_r = calc_ducts_area_weighted_average(hvac.Ducts, design_temp_values)
1191
+ return if (bldg_design_loads.Heat_Tot == 0) || (hvac.HeatingLoadFraction == 0) || hvac.Ducts.empty?
1112
1192
 
1113
- # ASHRAE 152 6.5.2
1114
- # For systems with ducts in several locations, Fregain shall be weighted by the fraction of exposed duct area
1115
- # in each space. Fregain shall be calculated separately for supply and return locations.
1116
- dse_Fregains = {}
1117
- hvac.Ducts.each do |duct|
1118
- dse_Fregains[duct.Location] = get_duct_regain_factor(duct)
1119
- end
1120
- fregain_values = { HPXML::DuctTypeSupply => dse_Fregains, HPXML::DuctTypeReturn => dse_Fregains }
1121
- dse_Fregain_s, dse_Fregain_r = calc_ducts_area_weighted_average(hvac.Ducts, fregain_values)
1193
+ init_heat_load = bldg_design_loads.Heat_Tot * hvac.HeatingLoadFraction
1122
1194
 
1123
- # Initialize for the iteration
1124
- delta = 1
1125
- heatingLoad_Prev = init_heat_load
1126
- heat_cfm = calc_airflow_rate(init_heat_load, (hvac.SupplyAirTemp - @heat_setpoint))
1195
+ # Distribution system efficiency (DSE) calculations based on ASHRAE Standard 152
1196
+ dse_As, dse_Ar = calc_ducts_areas(hvac.Ducts)
1197
+ supply_r, return_r = calc_ducts_rvalues(hvac.Ducts)
1127
1198
 
1128
- for _iter in 0..19
1129
- break if delta.abs <= 0.001
1199
+ design_temp_values = { HPXML::DuctTypeSupply => @heat_design_temps, HPXML::DuctTypeReturn => @heat_design_temps }
1200
+ dse_Tamb_heating_s, dse_Tamb_heating_r = calc_ducts_area_weighted_average(hvac.Ducts, design_temp_values)
1130
1201
 
1131
- dse_Qs, dse_Qr = calc_ducts_leakages(hvac.Ducts, heat_cfm)
1202
+ # ASHRAE 152 6.5.2
1203
+ # For systems with ducts in several locations, F_regain shall be weighted by the fraction of exposed duct area
1204
+ # in each space. F_regain shall be calculated separately for supply and return locations.
1205
+ dse_Fregains = {}
1206
+ hvac.Ducts.each do |duct|
1207
+ dse_Fregains[duct.Location] = get_duct_regain_factor(duct)
1208
+ end
1209
+ fregain_values = { HPXML::DuctTypeSupply => dse_Fregains, HPXML::DuctTypeReturn => dse_Fregains }
1210
+ dse_Fregain_s, dse_Fregain_r = calc_ducts_area_weighted_average(hvac.Ducts, fregain_values)
1132
1211
 
1133
- dse_DE = calc_delivery_effectiveness_heating(dse_Qs, dse_Qr, heat_cfm, heatingLoad_Prev, dse_Tamb_heating_s, dse_Tamb_heating_r, dse_As, dse_Ar, @heat_setpoint, dse_Fregain_s, dse_Fregain_r, supply_r, return_r)
1212
+ # Initialize for the iteration
1213
+ delta = 1
1214
+ heat_load_next = init_heat_load
1134
1215
 
1135
- # Calculate the increase in heating load due to ducts (Approach: DE = Qload/Qequip -> Qducts = Qequip-Qload)
1136
- heatingLoad_Next = init_heat_load / dse_DE
1216
+ for _iter in 0..19
1217
+ break if delta.abs <= 0.001
1137
1218
 
1138
- # Calculate the change since the last iteration
1139
- delta = (heatingLoad_Next - heatingLoad_Prev) / heatingLoad_Prev
1219
+ heat_load_prev = heat_load_next
1140
1220
 
1141
- # Update the flow rate for the next iteration
1142
- heatingLoad_Prev = heatingLoad_Next
1143
- heat_cfm = calc_airflow_rate(heatingLoad_Next, (hvac.SupplyAirTemp - @heat_setpoint))
1221
+ # Calculate the new heating air flow rate
1222
+ heat_cfm = calc_airflow_rate(heat_load_next, (hvac.SupplyAirTemp - @heat_setpoint))
1144
1223
 
1145
- end
1224
+ dse_Qs, dse_Qr = calc_ducts_leakages(hvac.Ducts, heat_cfm)
1225
+
1226
+ dse_DE = calc_delivery_effectiveness_heating(dse_Qs, dse_Qr, heat_cfm, heat_load_next, dse_Tamb_heating_s, dse_Tamb_heating_r, dse_As, dse_Ar, @heat_setpoint, dse_Fregain_s, dse_Fregain_r, supply_r, return_r)
1146
1227
 
1147
- hvac_final_values.Heat_Load_Ducts = heatingLoad_Next - init_heat_load
1148
- hvac_final_values.Heat_Load = init_heat_load + hvac_final_values.Heat_Load_Ducts
1228
+ # Calculate the increase in heating load due to ducts (Approach: DE = Qload/Qequip -> Qducts = Qequip-Qload)
1229
+ heat_load_next = init_heat_load / dse_DE
1230
+
1231
+ # Calculate the change since the last iteration
1232
+ delta = (heat_load_next - heat_load_prev) / heat_load_prev
1149
1233
  end
1234
+
1235
+ ducts_heat_load = heat_load_next - init_heat_load
1236
+
1237
+ bldg_design_loads.Heat_Ducts += ducts_heat_load
1238
+ bldg_design_loads.Heat_Tot += ducts_heat_load
1150
1239
  end
1151
1240
 
1152
- def self.process_duct_loads_cooling(hvac_final_values, weather, hvac, init_cool_load_sens, init_cool_load_lat)
1241
+ def self.apply_load_ducts_cooling(bldg_design_loads, weather, hvac)
1153
1242
  '''
1154
1243
  Cooling Duct Loads
1155
1244
  '''
1245
+ return if (bldg_design_loads.Cool_Sens == 0) || (hvac.CoolingLoadFraction == 0) || hvac.Ducts.empty?
1156
1246
 
1157
- if (init_cool_load_sens == 0) || (hvac.Ducts.size == 0)
1158
- hvac_final_values.Cool_Load_Ducts_Sens = 0.0
1159
- hvac_final_values.Cool_Load_Ducts_Tot = 0.0
1160
- hvac_final_values.Cool_Load_Sens = init_cool_load_sens
1161
- hvac_final_values.Cool_Load_Lat = init_cool_load_lat
1162
- hvac_final_values.Cool_Load_Tot = hvac_final_values.Cool_Load_Sens + hvac_final_values.Cool_Load_Lat
1163
- else
1164
- # Distribution system efficiency (DSE) calculations based on ASHRAE Standard 152
1165
- dse_As, dse_Ar = calc_ducts_areas(hvac.Ducts)
1166
- supply_r, return_r = calc_ducts_rvalues(hvac.Ducts)
1167
-
1168
- design_temp_values = { HPXML::DuctTypeSupply => @cool_design_temps, HPXML::DuctTypeReturn => @cool_design_temps }
1169
- dse_Tamb_cooling_s, dse_Tamb_cooling_r = calc_ducts_area_weighted_average(hvac.Ducts, design_temp_values)
1170
-
1171
- # ASHRAE 152 6.5.2
1172
- # For systems with ducts in several locations, Fregain shall be weighted by the fraction of exposed duct area
1173
- # in each space. Fregain shall be calculated separately for supply and return locations.
1174
- dse_Fregains = {}
1175
- hvac.Ducts.each do |duct|
1176
- dse_Fregains[duct.Location] = get_duct_regain_factor(duct)
1177
- end
1178
- fregain_values = { HPXML::DuctTypeSupply => dse_Fregains, HPXML::DuctTypeReturn => dse_Fregains }
1179
- dse_Fregain_s, dse_Fregain_r = calc_ducts_area_weighted_average(hvac.Ducts, fregain_values)
1247
+ init_cool_load_sens = bldg_design_loads.Cool_Sens * hvac.CoolingLoadFraction
1248
+ init_cool_load_lat = bldg_design_loads.Cool_Lat * hvac.CoolingLoadFraction
1180
1249
 
1181
- # Calculate the air enthalpy in the return duct location for DSE calculations
1182
- dse_h_r = (1.006 * UnitConversions.convert(dse_Tamb_cooling_r, 'F', 'C') + weather.design.CoolingHumidityRatio * (2501.0 + 1.86 * UnitConversions.convert(dse_Tamb_cooling_r, 'F', 'C'))) * UnitConversions.convert(1.0, 'kJ', 'Btu') * UnitConversions.convert(1.0, 'lbm', 'kg')
1250
+ # Distribution system efficiency (DSE) calculations based on ASHRAE Standard 152
1251
+ dse_As, dse_Ar = calc_ducts_areas(hvac.Ducts)
1252
+ supply_r, return_r = calc_ducts_rvalues(hvac.Ducts)
1183
1253
 
1184
- # Initialize for the iteration
1185
- delta = 1
1186
- coolingLoad_Tot_Prev = init_cool_load_sens + init_cool_load_lat
1187
- coolingLoad_Tot_Next = init_cool_load_sens + init_cool_load_lat
1188
- hvac_final_values.Cool_Load_Tot = init_cool_load_sens + init_cool_load_lat
1189
- hvac_final_values.Cool_Load_Sens = init_cool_load_sens
1254
+ design_temp_values = { HPXML::DuctTypeSupply => @cool_design_temps, HPXML::DuctTypeReturn => @cool_design_temps }
1255
+ dse_Tamb_cooling_s, dse_Tamb_cooling_r = calc_ducts_area_weighted_average(hvac.Ducts, design_temp_values)
1190
1256
 
1191
- initial_Cool_Airflow = calc_airflow_rate(init_cool_load_sens, (@cool_setpoint - hvac.LeavingAirTemp))
1257
+ # ASHRAE 152 6.5.2
1258
+ # For systems with ducts in several locations, F_regain shall be weighted by the fraction of exposed duct area
1259
+ # in each space. F_regain shall be calculated separately for supply and return locations.
1260
+ dse_Fregains = {}
1261
+ hvac.Ducts.each do |duct|
1262
+ dse_Fregains[duct.Location] = get_duct_regain_factor(duct)
1263
+ end
1264
+ fregain_values = { HPXML::DuctTypeSupply => dse_Fregains, HPXML::DuctTypeReturn => dse_Fregains }
1265
+ dse_Fregain_s, dse_Fregain_r = calc_ducts_area_weighted_average(hvac.Ducts, fregain_values)
1192
1266
 
1193
- supply_leakage_cfm, return_leakage_cfm = calc_ducts_leakages(hvac.Ducts, initial_Cool_Airflow)
1267
+ # Calculate the air enthalpy in the return duct location for DSE calculations
1268
+ dse_h_r = (1.006 * UnitConversions.convert(dse_Tamb_cooling_r, 'F', 'C') + weather.design.CoolingHumidityRatio * (2501.0 + 1.86 * UnitConversions.convert(dse_Tamb_cooling_r, 'F', 'C'))) * UnitConversions.convert(1.0, 'kJ', 'Btu') * UnitConversions.convert(1.0, 'lbm', 'kg')
1194
1269
 
1195
- hvac_final_values.Cool_Load_Lat, hvac_final_values.Cool_Load_Sens = calculate_sensible_latent_split(return_leakage_cfm, coolingLoad_Tot_Next, init_cool_load_lat)
1270
+ # Initialize for the iteration
1271
+ delta = 1
1272
+ cool_load_tot_next = init_cool_load_sens + init_cool_load_lat
1196
1273
 
1197
- for _iter in 1..50
1198
- break if delta.abs <= 0.001
1274
+ cool_cfm = calc_airflow_rate(init_cool_load_sens, (@cool_setpoint - hvac.LeavingAirTemp))
1275
+ dse_Qs, dse_Qr = calc_ducts_leakages(hvac.Ducts, cool_cfm)
1199
1276
 
1200
- coolingLoad_Tot_Prev = coolingLoad_Tot_Next
1277
+ for _iter in 1..50
1278
+ break if delta.abs <= 0.001
1201
1279
 
1202
- hvac_final_values.Cool_Load_Lat, hvac_final_values.Cool_Load_Sens = calculate_sensible_latent_split(return_leakage_cfm, coolingLoad_Tot_Next, init_cool_load_lat)
1203
- hvac_final_values.Cool_Load_Tot = hvac_final_values.Cool_Load_Lat + hvac_final_values.Cool_Load_Sens
1280
+ cool_load_tot_prev = cool_load_tot_next
1204
1281
 
1205
- # Calculate the new cooling air flow rate
1206
- cool_Airflow = calc_airflow_rate(hvac_final_values.Cool_Load_Sens, (@cool_setpoint - hvac.LeavingAirTemp))
1282
+ cool_load_lat, cool_load_sens = calculate_sensible_latent_split(dse_Qr, cool_load_tot_next, init_cool_load_lat)
1283
+ cool_load_tot = cool_load_lat + cool_load_sens
1207
1284
 
1208
- hvac_final_values.Cool_Load_Ducts_Sens = hvac_final_values.Cool_Load_Sens - init_cool_load_sens
1209
- hvac_final_values.Cool_Load_Ducts_Tot = coolingLoad_Tot_Next - (init_cool_load_sens + init_cool_load_lat)
1285
+ # Calculate the new cooling air flow rate
1286
+ cool_cfm = calc_airflow_rate(cool_load_sens, (@cool_setpoint - hvac.LeavingAirTemp))
1210
1287
 
1211
- dse_Qs, dse_Qr = calc_ducts_leakages(hvac.Ducts, cool_Airflow)
1288
+ dse_Qs, dse_Qr = calc_ducts_leakages(hvac.Ducts, cool_cfm)
1212
1289
 
1213
- dse_DE, dse_dTe_cooling, hvac_final_values.Cool_Load_Ducts_Sens = calc_delivery_effectiveness_cooling(dse_Qs, dse_Qr, hvac.LeavingAirTemp, cool_Airflow, hvac_final_values.Cool_Load_Sens, dse_Tamb_cooling_s, dse_Tamb_cooling_r, dse_As, dse_Ar, @cool_setpoint, dse_Fregain_s, dse_Fregain_r, hvac_final_values.Cool_Load_Tot, dse_h_r, supply_r, return_r)
1290
+ dse_DE, dse_dTe_cooling, cool_duct_sens = calc_delivery_effectiveness_cooling(dse_Qs, dse_Qr, hvac.LeavingAirTemp, cool_cfm, cool_load_sens, dse_Tamb_cooling_s, dse_Tamb_cooling_r, dse_As, dse_Ar, @cool_setpoint, dse_Fregain_s, dse_Fregain_r, cool_load_tot, dse_h_r, supply_r, return_r)
1214
1291
 
1215
- coolingLoad_Tot_Next = (init_cool_load_sens + init_cool_load_lat) / dse_DE
1292
+ cool_load_tot_next = (init_cool_load_sens + init_cool_load_lat) / dse_DE
1216
1293
 
1217
- # Calculate the change since the last iteration
1218
- delta = (coolingLoad_Tot_Next - coolingLoad_Tot_Prev) / coolingLoad_Tot_Prev
1219
- end
1294
+ # Calculate the change since the last iteration
1295
+ delta = (cool_load_tot_next - cool_load_tot_prev) / cool_load_tot_prev
1220
1296
  end
1221
1297
 
1222
- # Calculate the air flow rate required for design conditions
1223
- hvac_final_values.Cool_Airflow = calc_airflow_rate(hvac_final_values.Cool_Load_Sens, (@cool_setpoint - hvac.LeavingAirTemp))
1298
+ ducts_cool_load_sens = cool_load_sens - init_cool_load_sens
1299
+ ducts_cool_load_lat = cool_load_lat - init_cool_load_lat
1224
1300
 
1225
- hvac_final_values.Cool_Load_Ducts_Lat = hvac_final_values.Cool_Load_Ducts_Tot - hvac_final_values.Cool_Load_Ducts_Sens
1301
+ bldg_design_loads.Cool_Ducts_Sens += ducts_cool_load_sens
1302
+ bldg_design_loads.Cool_Sens += ducts_cool_load_sens
1303
+ bldg_design_loads.Cool_Ducts_Lat += ducts_cool_load_lat
1304
+ bldg_design_loads.Cool_Lat += ducts_cool_load_lat
1305
+ bldg_design_loads.Cool_Tot += ducts_cool_load_sens + ducts_cool_load_lat
1226
1306
  end
1227
1307
 
1228
- def self.process_equipment_adjustments(hvac_final_values, weather, hvac)
1308
+ def self.apply_hvac_equipment_adjustments(hvac_sizing_values, weather, hvac, cfa)
1229
1309
  '''
1230
1310
  Equipment Adjustments
1231
1311
  '''
@@ -1233,458 +1313,659 @@ class HVACSizing
1233
1313
  underSizeLimit = 0.9
1234
1314
 
1235
1315
  # Cooling
1236
- if hvac.has_type([Constants.ObjectNameCentralAirConditioner,
1237
- Constants.ObjectNameAirSourceHeatPump,
1238
- Constants.ObjectNameMiniSplitHeatPump,
1239
- Constants.ObjectNameRoomAirConditioner,
1240
- Constants.ObjectNameGroundSourceHeatPump])
1241
1316
 
1242
- if hvac_final_values.Cool_Load_Tot < 0
1243
- hvac_final_values.Cool_Capacity = @min_cooling_capacity
1244
- hvac_final_values.Cool_Capacity_Sens = 0.78 * @min_cooling_capacity
1245
- hvac_final_values.Cool_Airflow = 400.0 * UnitConversions.convert(@min_cooling_capacity, 'Btu/hr', 'ton')
1246
- end
1317
+ # Calculate the air flow rate required for design conditions
1318
+ hvac_sizing_values.Cool_Airflow = calc_airflow_rate(hvac_sizing_values.Cool_Load_Sens, (@cool_setpoint - hvac.LeavingAirTemp))
1247
1319
 
1248
- # Adjust the total cooling capacity to the rated conditions using performance curves
1249
- if not hvac.has_type(Constants.ObjectNameGroundSourceHeatPump)
1250
- enteringTemp = weather.design.CoolingDrybulb
1251
- else
1252
- enteringTemp = hvac.GSHP_HXCHWDesign
1253
- end
1320
+ if hvac_sizing_values.Cool_Load_Tot <= 0
1254
1321
 
1255
- if hvac.has_type([Constants.ObjectNameCentralAirConditioner,
1256
- Constants.ObjectNameAirSourceHeatPump])
1322
+ hvac_sizing_values.Cool_Capacity = 0.0
1323
+ hvac_sizing_values.Cool_Capacity_Sens = 0.0
1324
+ hvac_sizing_values.Cool_Airflow = 0.0
1257
1325
 
1258
- hvac.SizingSpeed = get_sizing_speed(hvac)
1259
- coefficients = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed]
1326
+ elsif [HPXML::HVACTypeCentralAirConditioner,
1327
+ HPXML::HVACTypeHeatPumpAirToAir].include? hvac.CoolType
1260
1328
 
1261
- totalCap_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, enteringTemp, coefficients)
1262
- coolCap_Rated = hvac_final_values.Cool_Load_Tot / totalCap_CurveValue
1329
+ enteringTemp = weather.design.CoolingDrybulb
1330
+ coefficients = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed]
1263
1331
 
1264
- sensCap_Rated = coolCap_Rated * hvac.SHRRated[hvac.SizingSpeed]
1332
+ totalCap_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, enteringTemp, coefficients)
1333
+ coolCap_Rated = hvac_sizing_values.Cool_Load_Tot / totalCap_CurveValue
1265
1334
 
1266
- sensibleCap_CurveValue = process_curve_fit(hvac_final_values.Cool_Airflow, hvac_final_values.Cool_Load_Tot, enteringTemp)
1267
- sensCap_Design = sensCap_Rated * sensibleCap_CurveValue
1268
- latCap_Design = [hvac_final_values.Cool_Load_Tot - sensCap_Design, 1.0].max
1335
+ sensCap_Rated = coolCap_Rated * hvac.SHRRated[hvac.SizingSpeed]
1269
1336
 
1270
- a_sens = @shr_biquadratic[0]
1271
- b_sens = @shr_biquadratic[1]
1272
- c_sens = @shr_biquadratic[3]
1273
- d_sens = @shr_biquadratic[5]
1337
+ sensibleCap_CurveValue = process_curve_fit(hvac_sizing_values.Cool_Airflow, hvac_sizing_values.Cool_Load_Tot, enteringTemp)
1338
+ sensCap_Design = sensCap_Rated * sensibleCap_CurveValue
1339
+ latCap_Design = [hvac_sizing_values.Cool_Load_Tot - sensCap_Design, 1.0].max
1274
1340
 
1275
- # Adjust Sizing
1276
- if latCap_Design < hvac_final_values.Cool_Load_Lat
1277
- # Size by MJ8 Latent load, return to rated conditions
1341
+ shr_biquadratic = get_shr_biquadratic
1342
+ a_sens = shr_biquadratic[0]
1343
+ b_sens = shr_biquadratic[1]
1344
+ c_sens = shr_biquadratic[3]
1345
+ d_sens = shr_biquadratic[5]
1278
1346
 
1279
- # Solve for the new sensible and total capacity at design conditions:
1280
- # CoolingLoad_Lat = cool_Capacity_Design - cool_Load_SensCap_Design
1281
- # solve the following for cool_Capacity_Design: SensCap_Design = SHRRated * cool_Capacity_Design / TotalCap_CurveValue * function(CFM/cool_Capacity_Design, ODB)
1282
- # substituting in CFM = cool_Load_SensCap_Design / (1.1 * ACF * (cool_setpoint - LAT))
1347
+ # Adjust Sizing
1348
+ if latCap_Design < hvac_sizing_values.Cool_Load_Lat
1349
+ # Size by MJ8 Latent load, return to rated conditions
1283
1350
 
1284
- cool_Load_SensCap_Design = hvac_final_values.Cool_Load_Lat / ((totalCap_CurveValue / hvac.SHRRated[hvac.SizingSpeed] - \
1285
- (UnitConversions.convert(b_sens, 'ton', 'Btu/hr') + UnitConversions.convert(d_sens, 'ton', 'Btu/hr') * enteringTemp) / \
1286
- (1.1 * @acf * (@cool_setpoint - hvac.LeavingAirTemp))) / \
1287
- (a_sens + c_sens * enteringTemp) - 1.0)
1351
+ # Solve for the new sensible and total capacity at design conditions:
1352
+ # CoolingLoad_Lat = cool_Capacity_Design - cool_Load_SensCap_Design
1353
+ # solve the following for cool_Capacity_Design: SensCap_Design = SHRRated * cool_Capacity_Design / TotalCap_CurveValue * function(CFM/cool_Capacity_Design, ODB)
1354
+ # substituting in CFM = cool_Load_SensCap_Design / (1.1 * ACF * (cool_setpoint - LAT))
1288
1355
 
1289
- cool_Capacity_Design = cool_Load_SensCap_Design + hvac_final_values.Cool_Load_Lat
1356
+ cool_Load_SensCap_Design = hvac_sizing_values.Cool_Load_Lat / ((totalCap_CurveValue / hvac.SHRRated[hvac.SizingSpeed] - \
1357
+ (UnitConversions.convert(b_sens, 'ton', 'Btu/hr') + UnitConversions.convert(d_sens, 'ton', 'Btu/hr') * enteringTemp) / \
1358
+ (1.1 * @acf * (@cool_setpoint - hvac.LeavingAirTemp))) / \
1359
+ (a_sens + c_sens * enteringTemp) - 1.0)
1290
1360
 
1291
- # The SHR of the equipment at the design condition
1292
- sHR_design = cool_Load_SensCap_Design / cool_Capacity_Design
1361
+ cool_Capacity_Design = cool_Load_SensCap_Design + hvac_sizing_values.Cool_Load_Lat
1293
1362
 
1294
- # If the adjusted equipment size is negative (occurs at altitude), use oversize limit (the adjustment
1295
- # almost always hits the oversize limit in this case, making this a safe assumption)
1296
- if (cool_Capacity_Design < 0) || (cool_Load_SensCap_Design < 0)
1297
- cool_Capacity_Design = hvac.OverSizeLimit * hvac_final_values.Cool_Load_Tot
1298
- end
1363
+ # The SHR of the equipment at the design condition
1364
+ sHR_design = cool_Load_SensCap_Design / cool_Capacity_Design
1299
1365
 
1300
- # Limit total capacity to oversize limit
1301
- cool_Capacity_Design = [cool_Capacity_Design, hvac.OverSizeLimit * hvac_final_values.Cool_Load_Tot].min
1366
+ # If the adjusted equipment size is negative (occurs at altitude), use oversize limit (the adjustment
1367
+ # almost always hits the oversize limit in this case, making this a safe assumption)
1368
+ if (cool_Capacity_Design < 0) || (cool_Load_SensCap_Design < 0)
1369
+ cool_Capacity_Design = hvac.OverSizeLimit * hvac_sizing_values.Cool_Load_Tot
1370
+ end
1302
1371
 
1303
- # Determine the final sensible capacity at design using the SHR
1304
- cool_Load_SensCap_Design = sHR_design * cool_Capacity_Design
1372
+ # Limit total capacity to oversize limit
1373
+ cool_Capacity_Design = [cool_Capacity_Design, hvac.OverSizeLimit * hvac_sizing_values.Cool_Load_Tot].min
1305
1374
 
1306
- # Calculate the final air flow rate using final sensible capacity at design
1307
- hvac_final_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
1375
+ # Determine the final sensible capacity at design using the SHR
1376
+ cool_Load_SensCap_Design = sHR_design * cool_Capacity_Design
1308
1377
 
1309
- # Determine rated capacities
1310
- hvac_final_values.Cool_Capacity = cool_Capacity_Design / totalCap_CurveValue
1311
- hvac_final_values.Cool_Capacity_Sens = hvac_final_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1378
+ # Calculate the final air flow rate using final sensible capacity at design
1379
+ hvac_sizing_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
1312
1380
 
1313
- elsif sensCap_Design < underSizeLimit * hvac_final_values.Cool_Load_Sens
1314
- # Size by MJ8 Sensible load, return to rated conditions, find Sens with SHRRated. Limit total
1315
- # capacity to oversizing limit
1381
+ # Determine rated capacities
1382
+ hvac_sizing_values.Cool_Capacity = cool_Capacity_Design / totalCap_CurveValue
1383
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1316
1384
 
1317
- sensCap_Design = underSizeLimit * hvac_final_values.Cool_Load_Sens
1385
+ elsif sensCap_Design < underSizeLimit * hvac_sizing_values.Cool_Load_Sens
1386
+ # Size by MJ8 Sensible load, return to rated conditions, find Sens with SHRRated. Limit total
1387
+ # capacity to oversizing limit
1318
1388
 
1319
- # Solve for the new total system capacity at design conditions:
1320
- # SensCap_Design = SensCap_Rated * SensibleCap_CurveValue
1321
- # = SHRRated * cool_Capacity_Design / TotalCap_CurveValue * SensibleCap_CurveValue
1322
- # = SHRRated * cool_Capacity_Design / TotalCap_CurveValue * function(CFM/cool_Capacity_Design, ODB)
1389
+ sensCap_Design = underSizeLimit * hvac_sizing_values.Cool_Load_Sens
1323
1390
 
1324
- cool_Capacity_Design = (sensCap_Design / (hvac.SHRRated[hvac.SizingSpeed] / totalCap_CurveValue) - \
1325
- (b_sens * UnitConversions.convert(hvac_final_values.Cool_Airflow, 'ton', 'Btu/hr') + \
1326
- d_sens * UnitConversions.convert(hvac_final_values.Cool_Airflow, 'ton', 'Btu/hr') * enteringTemp)) / \
1327
- (a_sens + c_sens * enteringTemp)
1391
+ # Solve for the new total system capacity at design conditions:
1392
+ # SensCap_Design = SensCap_Rated * SensibleCap_CurveValue
1393
+ # = SHRRated * cool_Capacity_Design / TotalCap_CurveValue * SensibleCap_CurveValue
1394
+ # = SHRRated * cool_Capacity_Design / TotalCap_CurveValue * function(CFM/cool_Capacity_Design, ODB)
1328
1395
 
1329
- # Limit total capacity to oversize limit
1330
- cool_Capacity_Design = [cool_Capacity_Design, hvac.OverSizeLimit * hvac_final_values.Cool_Load_Tot].min
1396
+ cool_Capacity_Design = (sensCap_Design / (hvac.SHRRated[hvac.SizingSpeed] / totalCap_CurveValue) - \
1397
+ (b_sens * UnitConversions.convert(hvac_sizing_values.Cool_Airflow, 'ton', 'Btu/hr') + \
1398
+ d_sens * UnitConversions.convert(hvac_sizing_values.Cool_Airflow, 'ton', 'Btu/hr') * enteringTemp)) / \
1399
+ (a_sens + c_sens * enteringTemp)
1331
1400
 
1332
- hvac_final_values.Cool_Capacity = cool_Capacity_Design / totalCap_CurveValue
1333
- hvac_final_values.Cool_Capacity_Sens = hvac_final_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1401
+ # Limit total capacity to oversize limit
1402
+ cool_Capacity_Design = [cool_Capacity_Design, hvac.OverSizeLimit * hvac_sizing_values.Cool_Load_Tot].min
1334
1403
 
1335
- # Recalculate the air flow rate in case the oversizing limit has been used
1336
- cool_Load_SensCap_Design = hvac_final_values.Cool_Capacity_Sens * sensibleCap_CurveValue
1337
- hvac_final_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
1404
+ hvac_sizing_values.Cool_Capacity = cool_Capacity_Design / totalCap_CurveValue
1405
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1338
1406
 
1339
- else
1340
- hvac_final_values.Cool_Capacity = hvac_final_values.Cool_Load_Tot / totalCap_CurveValue
1341
- hvac_final_values.Cool_Capacity_Sens = hvac_final_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1407
+ # Recalculate the air flow rate in case the oversizing limit has been used
1408
+ cool_Load_SensCap_Design = hvac_sizing_values.Cool_Capacity_Sens * sensibleCap_CurveValue
1409
+ hvac_sizing_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
1342
1410
 
1343
- cool_Load_SensCap_Design = hvac_final_values.Cool_Capacity_Sens * sensibleCap_CurveValue
1344
- hvac_final_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
1345
- end
1411
+ else
1412
+ hvac_sizing_values.Cool_Capacity = hvac_sizing_values.Cool_Load_Tot / totalCap_CurveValue
1413
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1346
1414
 
1347
- # Ensure the air flow rate is in between 200 and 500 cfm/ton.
1348
- # Reset the air flow rate (with a safety margin), if required.
1349
- if hvac_final_values.Cool_Airflow / UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'ton') > 500
1350
- hvac_final_values.Cool_Airflow = 499.0 * UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'ton') # CFM
1351
- elsif hvac_final_values.Cool_Airflow / UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'ton') < 200
1352
- hvac_final_values.Cool_Airflow = 201.0 * UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'ton') # CFM
1353
- end
1415
+ cool_Load_SensCap_Design = hvac_sizing_values.Cool_Capacity_Sens * sensibleCap_CurveValue
1416
+ hvac_sizing_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
1417
+ end
1354
1418
 
1355
- elsif hvac.has_type(Constants.ObjectNameMiniSplitHeatPump)
1419
+ # Ensure the air flow rate is in between 200 and 500 cfm/ton.
1420
+ # Reset the air flow rate (with a safety margin), if required.
1421
+ if hvac_sizing_values.Cool_Airflow / UnitConversions.convert(hvac_sizing_values.Cool_Capacity, 'Btu/hr', 'ton') > 500
1422
+ hvac_sizing_values.Cool_Airflow = 499.0 * UnitConversions.convert(hvac_sizing_values.Cool_Capacity, 'Btu/hr', 'ton') # CFM
1423
+ elsif hvac_sizing_values.Cool_Airflow / UnitConversions.convert(hvac_sizing_values.Cool_Capacity, 'Btu/hr', 'ton') < 200
1424
+ hvac_sizing_values.Cool_Airflow = 201.0 * UnitConversions.convert(hvac_sizing_values.Cool_Capacity, 'Btu/hr', 'ton') # CFM
1425
+ end
1356
1426
 
1357
- hvac.SizingSpeed = get_sizing_speed(hvac)
1358
- coefficients = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed]
1427
+ elsif [HPXML::HVACTypeHeatPumpMiniSplit,
1428
+ HPXML::HVACTypeMiniSplitAirConditioner].include? hvac.CoolType
1359
1429
 
1360
- totalCap_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, enteringTemp, coefficients)
1430
+ enteringTemp = weather.design.CoolingDrybulb
1431
+ coefficients = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed]
1361
1432
 
1362
- hvac_final_values.Cool_Capacity = (hvac_final_values.Cool_Load_Tot / totalCap_CurveValue)
1363
- hvac_final_values.Cool_Capacity_Sens = hvac_final_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1364
- hvac_final_values.Cool_Airflow = hvac.RatedCFMperTonCooling[-1] * UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'ton')
1433
+ totalCap_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, enteringTemp, coefficients)
1365
1434
 
1366
- elsif hvac.has_type(Constants.ObjectNameRoomAirConditioner)
1435
+ hvac_sizing_values.Cool_Capacity = (hvac_sizing_values.Cool_Load_Tot / totalCap_CurveValue)
1436
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1437
+ # FIXME: Why not use calc_airflow_rate?
1438
+ hvac_sizing_values.Cool_Airflow = hvac.RatedCFMperTonCooling[-1] * hvac.CapacityRatioCooling[-1] * UnitConversions.convert(hvac_sizing_values.Cool_Capacity, 'Btu/hr', 'ton')
1367
1439
 
1368
- hvac.SizingSpeed = 0
1369
- totalCap_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, enteringTemp, hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed])
1440
+ elsif hvac.CoolType == HPXML::HVACTypeRoomAirConditioner
1370
1441
 
1371
- hvac_final_values.Cool_Capacity = hvac_final_values.Cool_Load_Tot / totalCap_CurveValue
1372
- hvac_final_values.Cool_Capacity_Sens = hvac_final_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1373
- hvac_final_values.Cool_Airflow = hvac.RatedCFMperTonCooling[hvac.SizingSpeed] * UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'ton')
1442
+ enteringTemp = weather.design.CoolingDrybulb
1443
+ totalCap_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, enteringTemp, hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed])
1374
1444
 
1375
- elsif hvac.has_type(Constants.ObjectNameGroundSourceHeatPump)
1445
+ hvac_sizing_values.Cool_Capacity = hvac_sizing_values.Cool_Load_Tot / totalCap_CurveValue
1446
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1447
+ # FIXME: Why not use calc_airflow_rate?
1448
+ hvac_sizing_values.Cool_Airflow = hvac.RatedCFMperTonCooling[hvac.SizingSpeed] * UnitConversions.convert(hvac_sizing_values.Cool_Capacity, 'Btu/hr', 'ton')
1376
1449
 
1377
- # Single speed as current
1378
- hvac.SizingSpeed = 0
1379
- totalCap_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, enteringTemp, hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed])
1380
- sensibleCap_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, enteringTemp, hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed])
1381
- bypassFactor_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, @cool_setpoint, hvac.COIL_BF_FT_SPEC[hvac.SizingSpeed])
1450
+ elsif hvac.CoolType == HPXML::HVACTypeHeatPumpGroundToAir
1451
+ coil_bf = gshp_coil_bf
1452
+ enteringTemp = hvac.GSHP_design_chw
1382
1453
 
1383
- hvac_final_values.Cool_Capacity = hvac_final_values.Cool_Load_Tot / totalCap_CurveValue # Note: cool_Capacity_Design = hvac_final_values.Cool_Load_Tot
1384
- hvac_final_values.Cool_Capacity_Sens = hvac_final_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1454
+ # Neglecting the water flow rate for now because it's not available yet. Air flow rate is pre-adjusted values.
1455
+ design_wb_temp = UnitConversions.convert(@wetbulb_indoor_cooling, 'f', 'k')
1456
+ design_db_temp = UnitConversions.convert(@cool_setpoint, 'f', 'k')
1457
+ design_w_temp = UnitConversions.convert(enteringTemp, 'f', 'k')
1458
+ design_vfr_air = UnitConversions.convert(hvac_sizing_values.Cool_Airflow, 'cfm', 'm^3/s')
1385
1459
 
1386
- cool_Load_SensCap_Design = (hvac_final_values.Cool_Capacity_Sens * sensibleCap_CurveValue /
1387
- (1.0 + (1.0 - hvac.CoilBF * bypassFactor_CurveValue) *
1388
- (80.0 - @cool_setpoint) / (@cool_setpoint - hvac.LeavingAirTemp)))
1389
- cool_Load_LatCap_Design = hvac_final_values.Cool_Load_Tot - cool_Load_SensCap_Design
1460
+ totalCap_CurveValue, sensibleCap_CurveValue = calc_gshp_clg_curve_value(hvac, design_wb_temp, design_db_temp, design_w_temp, design_vfr_air, nil)
1390
1461
 
1391
- # Adjust Sizing so that coil sensible at design >= CoolingLoad_MJ8_Sens, and coil latent at design >= CoolingLoad_MJ8_Lat, and equipment SHRRated is maintained.
1392
- cool_Load_SensCap_Design = [cool_Load_SensCap_Design, hvac_final_values.Cool_Load_Sens].max
1393
- cool_Load_LatCap_Design = [cool_Load_LatCap_Design, hvac_final_values.Cool_Load_Lat].max
1394
- cool_Capacity_Design = cool_Load_SensCap_Design + cool_Load_LatCap_Design
1462
+ bypassFactor_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, @cool_setpoint, gshp_coil_bf_ft_spec)
1395
1463
 
1396
- # Limit total capacity via oversizing limit
1397
- cool_Capacity_Design = [cool_Capacity_Design, hvac.OverSizeLimit * hvac_final_values.Cool_Load_Tot].min
1398
- hvac_final_values.Cool_Capacity = cool_Capacity_Design / totalCap_CurveValue
1399
- hvac_final_values.Cool_Capacity_Sens = hvac_final_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1464
+ hvac_sizing_values.Cool_Capacity = hvac_sizing_values.Cool_Load_Tot / totalCap_CurveValue # Note: cool_Capacity_Design = hvac_sizing_values.Cool_Load_Tot
1465
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1400
1466
 
1401
- # Recalculate the air flow rate in case the oversizing limit has been used
1402
- cool_Load_SensCap_Design = (hvac_final_values.Cool_Capacity_Sens * sensibleCap_CurveValue /
1403
- (1.0 + (1.0 - hvac.CoilBF * bypassFactor_CurveValue) *
1404
- (80.0 - @cool_setpoint) / (@cool_setpoint - hvac.LeavingAirTemp)))
1405
- hvac_final_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
1406
- else
1467
+ cool_Load_SensCap_Design = (hvac_sizing_values.Cool_Capacity_Sens * sensibleCap_CurveValue /
1468
+ (1.0 + (1.0 - coil_bf * bypassFactor_CurveValue) *
1469
+ (80.0 - @cool_setpoint) / (@cool_setpoint - hvac.LeavingAirTemp)))
1470
+ cool_Load_LatCap_Design = hvac_sizing_values.Cool_Load_Tot - cool_Load_SensCap_Design
1407
1471
 
1408
- fail 'Unexpected cooling system.'
1409
- end
1472
+ # Adjust Sizing so that coil sensible at design >= CoolingLoad_MJ8_Sens, and coil latent at design >= CoolingLoad_MJ8_Lat, and equipment SHRRated is maintained.
1473
+ cool_Load_SensCap_Design = [cool_Load_SensCap_Design, hvac_sizing_values.Cool_Load_Sens].max
1474
+ cool_Load_LatCap_Design = [cool_Load_LatCap_Design, hvac_sizing_values.Cool_Load_Lat].max
1475
+ cool_Capacity_Design = cool_Load_SensCap_Design + cool_Load_LatCap_Design
1410
1476
 
1411
- elsif hvac.has_type(Constants.ObjectNameEvaporativeCooler)
1412
- hvac_final_values.Cool_Capacity = hvac_final_values.Cool_Load_Tot
1413
- hvac_final_values.Cool_Capacity_Sens = hvac_final_values.Cool_Load_Sens
1477
+ # Limit total capacity via oversizing limit
1478
+ cool_Capacity_Design = [cool_Capacity_Design, hvac.OverSizeLimit * hvac_sizing_values.Cool_Load_Tot].min
1479
+ hvac_sizing_values.Cool_Capacity = cool_Capacity_Design / totalCap_CurveValue
1480
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1481
+
1482
+ # Recalculate the air flow rate in case the oversizing limit has been used
1483
+ cool_Load_SensCap_Design = (hvac_sizing_values.Cool_Capacity_Sens * sensibleCap_CurveValue /
1484
+ (1.0 + (1.0 - coil_bf * bypassFactor_CurveValue) *
1485
+ (80.0 - @cool_setpoint) / (@cool_setpoint - hvac.LeavingAirTemp)))
1486
+ hvac_sizing_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
1487
+
1488
+ elsif hvac.CoolType == HPXML::HVACTypeEvaporativeCooler
1489
+
1490
+ hvac_sizing_values.Cool_Capacity = hvac_sizing_values.Cool_Load_Tot
1491
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Load_Sens
1414
1492
  if @cool_setpoint - hvac.LeavingAirTemp > 0
1415
- hvac_final_values.Cool_Airflow = calc_airflow_rate(hvac_final_values.Cool_Load_Sens, (@cool_setpoint - hvac.LeavingAirTemp))
1493
+ hvac_sizing_values.Cool_Airflow = calc_airflow_rate(hvac_sizing_values.Cool_Load_Sens, (@cool_setpoint - hvac.LeavingAirTemp))
1416
1494
  else
1417
- cfa = UnitConversions.convert(@spaces[HPXML::LocationLivingSpace].floorArea, 'm^2', 'ft^2')
1418
- hvac_final_values.Cool_Airflow = cfa * 2.0 # Use industry rule of thumb sizing method adopted by HEScore
1495
+ hvac_sizing_values.Cool_Airflow = cfa * 2.0 # Use industry rule of thumb sizing method adopted by HEScore
1419
1496
  end
1420
1497
 
1421
- elsif hvac.has_type(Constants.ObjectNameWaterLoopHeatPump)
1498
+ elsif hvac.CoolType == HPXML::HVACTypeHeatPumpWaterLoopToAir
1499
+
1422
1500
  # Model only currently used for heating
1423
- hvac_final_values.Cool_Capacity = 0.0
1424
- hvac_final_values.Cool_Capacity_Sens = 0.0
1425
- hvac_final_values.Cool_Airflow = 0.0
1501
+ hvac_sizing_values.Cool_Capacity = 0.0
1502
+ hvac_sizing_values.Cool_Capacity_Sens = 0.0
1503
+ hvac_sizing_values.Cool_Airflow = 0.0
1504
+
1505
+ elsif hvac.CoolType.nil?
1506
+
1507
+ hvac_sizing_values.Cool_Capacity = 0.0
1508
+ hvac_sizing_values.Cool_Capacity_Sens = 0.0
1509
+ hvac_sizing_values.Cool_Airflow = 0.0
1426
1510
 
1427
1511
  else
1428
- hvac_final_values.Cool_Capacity = 0.0
1429
- hvac_final_values.Cool_Capacity_Sens = 0.0
1430
- hvac_final_values.Cool_Airflow = 0.0
1512
+
1513
+ fail "Unexpected cooling type: #{hvac.CoolType}."
1431
1514
 
1432
1515
  end
1433
1516
 
1434
1517
  # Heating
1435
- if hvac.has_type(Constants.ObjectNameAirSourceHeatPump)
1436
- hvac_final_values = process_heat_pump_adjustment(hvac_final_values, weather, hvac, totalCap_CurveValue)
1518
+ if hvac_sizing_values.Heat_Load <= 0
1437
1519
 
1438
- hvac_final_values.Heat_Capacity = hvac_final_values.Cool_Capacity
1439
- hvac_final_values.Heat_Capacity_Supp = hvac_final_values.Heat_Load
1520
+ hvac_sizing_values.Heat_Capacity = 0.0
1521
+ hvac_sizing_values.Heat_Capacity_Supp = 0.0
1522
+ hvac_sizing_values.Heat_Airflow = 0.0
1440
1523
 
1441
- if hvac_final_values.Cool_Capacity > @min_cooling_capacity
1442
- hvac_final_values.Heat_Airflow = calc_airflow_rate(hvac_final_values.Heat_Capacity, (hvac.SupplyAirTemp - @heat_setpoint))
1524
+ elsif hvac.HeatType == HPXML::HVACTypeHeatPumpAirToAir
1525
+
1526
+ if hvac_sizing_values.Cool_Capacity > 0
1527
+ process_heat_pump_adjustment(hvac_sizing_values, weather, hvac, totalCap_CurveValue)
1528
+ hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Cool_Capacity
1529
+ hvac_sizing_values.Heat_Capacity_Supp = hvac_sizing_values.Heat_Load
1443
1530
  else
1444
- hvac_final_values.Heat_Airflow = calc_airflow_rate(hvac_final_values.Heat_Capacity_Supp, (hvac.SupplyAirTemp - @heat_setpoint))
1531
+ hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Heat_Load
1532
+ hvac_sizing_values.Heat_Capacity_Supp = hvac_sizing_values.Heat_Load
1445
1533
  end
1534
+ hvac_sizing_values.Heat_Airflow = calc_airflow_rate(hvac_sizing_values.Heat_Capacity, (hvac.SupplyAirTemp - @heat_setpoint))
1446
1535
 
1447
- elsif hvac.has_type(Constants.ObjectNameMiniSplitHeatPump)
1448
- hvac_final_values = process_heat_pump_adjustment(hvac_final_values, weather, hvac, totalCap_CurveValue)
1536
+ elsif hvac.HeatType == HPXML::HVACTypeHeatPumpMiniSplit
1449
1537
 
1450
- hvac_final_values.Heat_Capacity = [hvac_final_values.Cool_Capacity + hvac.HeatingCapacityOffset, Constants.small].max
1451
- hvac_final_values.Heat_Capacity_Supp = hvac_final_values.Heat_Load
1538
+ if hvac_sizing_values.Cool_Capacity > 0
1539
+ process_heat_pump_adjustment(hvac_sizing_values, weather, hvac, totalCap_CurveValue)
1540
+ hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Cool_Capacity
1541
+ hvac_sizing_values.Heat_Capacity_Supp = hvac_sizing_values.Heat_Load
1542
+ else
1543
+ hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Heat_Load
1544
+ hvac_sizing_values.Heat_Capacity_Supp = hvac_sizing_values.Heat_Load
1545
+ end
1546
+ # FIXME: Why not use calc_airflow_rate?
1547
+ hvac_sizing_values.Heat_Airflow = hvac.RatedCFMperTonHeating[-1] * hvac.CapacityRatioHeating[-1] * UnitConversions.convert(hvac_sizing_values.Heat_Capacity, 'Btu/hr', 'ton') # Maximum air flow under heating operation
1452
1548
 
1453
- hvac_final_values.Heat_Airflow = hvac.RatedCFMperTonHeating[-1] * UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'ton') # Maximum air flow under heating operation
1549
+ elsif hvac.HeatType == HPXML::HVACTypeHeatPumpGroundToAir
1454
1550
 
1455
- elsif hvac.has_type(Constants.ObjectNameGroundSourceHeatPump)
1456
- hvac_final_values.Heat_Capacity = hvac_final_values.Heat_Load
1457
- hvac_final_values.Heat_Capacity_Supp = hvac_final_values.Heat_Load
1551
+ if hvac_sizing_values.Cool_Capacity > 0
1552
+ coil_bf = gshp_coil_bf
1553
+ hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Heat_Load
1554
+ hvac_sizing_values.Heat_Capacity_Supp = hvac_sizing_values.Heat_Load
1458
1555
 
1459
- # For single stage compressor, when heating capacity is much larger than cooling capacity,
1460
- # in order to avoid frequent cycling in cooling mode, heating capacity is derated to 75%.
1461
- if hvac_final_values.Heat_Capacity >= 1.5 * hvac_final_values.Cool_Capacity
1462
- hvac_final_values.Heat_Capacity = hvac_final_values.Heat_Load * 0.75
1463
- elsif hvac_final_values.Heat_Capacity < hvac_final_values.Cool_Capacity
1464
- hvac_final_values.Heat_Capacity_Supp = hvac_final_values.Heat_Capacity
1556
+ # For single stage compressor, when heating capacity is much larger than cooling capacity,
1557
+ # in order to avoid frequent cycling in cooling mode, heating capacity is derated to 75%.
1558
+ if hvac_sizing_values.Heat_Capacity >= 1.5 * hvac_sizing_values.Cool_Capacity
1559
+ hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Heat_Load * 0.75
1560
+ elsif hvac_sizing_values.Heat_Capacity < hvac_sizing_values.Cool_Capacity
1561
+ hvac_sizing_values.Heat_Capacity_Supp = hvac_sizing_values.Heat_Capacity
1562
+ end
1563
+
1564
+ hvac_sizing_values.Cool_Capacity = [hvac_sizing_values.Cool_Capacity, hvac_sizing_values.Heat_Capacity].max
1565
+ hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Cool_Capacity
1566
+
1567
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1568
+ cool_Load_SensCap_Design = (hvac_sizing_values.Cool_Capacity_Sens * sensibleCap_CurveValue /
1569
+ (1.0 + (1.0 - coil_bf * bypassFactor_CurveValue) *
1570
+ (80.0 - @cool_setpoint) / (@cool_setpoint - hvac.LeavingAirTemp)))
1571
+ hvac_sizing_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
1572
+ else
1573
+ hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Heat_Load
1574
+ hvac_sizing_values.Heat_Capacity_Supp = hvac_sizing_values.Heat_Load
1465
1575
  end
1576
+ hvac_sizing_values.Heat_Airflow = calc_airflow_rate(hvac_sizing_values.Heat_Capacity, (hvac.SupplyAirTemp - @heat_setpoint))
1466
1577
 
1467
- hvac_final_values.Cool_Capacity = [hvac_final_values.Cool_Capacity, hvac_final_values.Heat_Capacity].max
1468
- hvac_final_values.Heat_Capacity = hvac_final_values.Cool_Capacity
1578
+ elsif hvac.HeatType == HPXML::HVACTypeHeatPumpWaterLoopToAir
1469
1579
 
1470
- hvac_final_values.Cool_Capacity_Sens = hvac_final_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1471
- cool_Load_SensCap_Design = (hvac_final_values.Cool_Capacity_Sens * sensibleCap_CurveValue /
1472
- (1.0 + (1.0 - hvac.CoilBF * bypassFactor_CurveValue) *
1473
- (80.0 - @cool_setpoint) / (@cool_setpoint - hvac.LeavingAirTemp)))
1474
- hvac_final_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
1475
- hvac_final_values.Heat_Airflow = calc_airflow_rate(hvac_final_values.Heat_Capacity, (hvac.SupplyAirTemp - @heat_setpoint))
1580
+ hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Heat_Load
1581
+ hvac_sizing_values.Heat_Capacity_Supp = hvac_sizing_values.Heat_Load
1476
1582
 
1477
- elsif hvac.has_type(Constants.ObjectNameWaterLoopHeatPump)
1478
- hvac_final_values.Heat_Capacity = hvac_final_values.Heat_Load
1479
- hvac_final_values.Heat_Capacity_Supp = hvac_final_values.Heat_Load
1583
+ hvac_sizing_values.Heat_Airflow = calc_airflow_rate(hvac_sizing_values.Heat_Capacity, (hvac.SupplyAirTemp - @heat_setpoint))
1480
1584
 
1481
- hvac_final_values.Heat_Airflow = calc_airflow_rate(hvac_final_values.Heat_Capacity, (hvac.SupplyAirTemp - @heat_setpoint))
1585
+ elsif hvac.HeatType == HPXML::HVACTypeFurnace
1482
1586
 
1483
- elsif hvac.has_type(Constants.ObjectNameFurnace)
1484
- hvac_final_values.Heat_Capacity = hvac_final_values.Heat_Load
1485
- hvac_final_values.Heat_Capacity_Supp = 0.0
1587
+ hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Heat_Load
1588
+ hvac_sizing_values.Heat_Capacity_Supp = 0.0
1486
1589
 
1487
- hvac_final_values.Heat_Airflow = calc_airflow_rate(hvac_final_values.Heat_Capacity, (hvac.SupplyAirTemp - @heat_setpoint))
1590
+ hvac_sizing_values.Heat_Airflow = calc_airflow_rate(hvac_sizing_values.Heat_Capacity, (hvac.SupplyAirTemp - @heat_setpoint))
1488
1591
 
1489
- elsif hvac.has_type(Constants.ObjectNameUnitHeater)
1490
- hvac_final_values.Heat_Capacity = hvac_final_values.Heat_Load
1491
- hvac_final_values.Heat_Capacity_Supp = 0.0
1592
+ elsif [HPXML::HVACTypeStove,
1593
+ HPXML::HVACTypePortableHeater,
1594
+ HPXML::HVACTypeFixedHeater,
1595
+ HPXML::HVACTypeWallFurnace,
1596
+ HPXML::HVACTypeFloorFurnace,
1597
+ HPXML::HVACTypeFireplace].include? hvac.HeatType
1598
+
1599
+ hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Heat_Load
1600
+ hvac_sizing_values.Heat_Capacity_Supp = 0.0
1492
1601
 
1493
1602
  if hvac.RatedCFMperTonHeating[0] > 0
1494
1603
  # Fixed airflow rate
1495
- hvac_final_values.Heat_Airflow = UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'ton') * hvac.RatedCFMperTonHeating[0]
1604
+ # FIXME: Is this still needed?
1605
+ hvac_sizing_values.Heat_Airflow = UnitConversions.convert(hvac_sizing_values.Heat_Capacity, 'Btu/hr', 'ton') * hvac.RatedCFMperTonHeating[0]
1496
1606
  else
1497
1607
  # Autosized airflow rate
1498
- hvac_final_values.Heat_Airflow = calc_airflow_rate(hvac_final_values.Heat_Capacity, (hvac.SupplyAirTemp - @heat_setpoint))
1608
+ hvac_sizing_values.Heat_Airflow = calc_airflow_rate(hvac_sizing_values.Heat_Capacity, (hvac.SupplyAirTemp - @heat_setpoint))
1499
1609
  end
1500
1610
 
1501
- elsif hvac.has_type([Constants.ObjectNameBoiler,
1502
- Constants.ObjectNameElectricBaseboard])
1503
- hvac_final_values.Heat_Capacity = hvac_final_values.Heat_Load
1504
- hvac_final_values.Heat_Capacity_Supp = 0.0
1505
- hvac_final_values.Heat_Airflow = 0.0
1611
+ elsif [HPXML::HVACTypeBoiler,
1612
+ HPXML::HVACTypeElectricResistance].include? hvac.HeatType
1613
+
1614
+ hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Heat_Load
1615
+ hvac_sizing_values.Heat_Capacity_Supp = 0.0
1616
+ hvac_sizing_values.Heat_Airflow = 0.0
1617
+
1618
+ elsif hvac.HeatType.nil?
1619
+
1620
+ hvac_sizing_values.Heat_Capacity = 0.0
1621
+ hvac_sizing_values.Heat_Capacity_Supp = 0.0
1622
+ hvac_sizing_values.Heat_Airflow = 0.0
1506
1623
 
1507
1624
  else
1508
- hvac_final_values.Heat_Capacity = 0.0
1509
- hvac_final_values.Heat_Capacity_Supp = 0.0
1510
- hvac_final_values.Heat_Airflow = 0.0
1625
+
1626
+ fail "Unexpected heating type: #{hvac.HeatType}."
1511
1627
 
1512
1628
  end
1513
1629
  end
1514
1630
 
1515
- def self.process_fixed_equipment(hvac_final_values, hvac)
1631
+ def self.apply_hvac_installation_quality(hvac_sizing_values, weather, hvac)
1632
+ # Increases the autosized heating/cooling capacities to account for any reduction
1633
+ # in capacity due to HVAC installation quality. This is done to prevent causing
1634
+ # unmet loads.
1635
+
1636
+ return unless [HPXML::HVACTypeCentralAirConditioner,
1637
+ HPXML::HVACTypeHeatPumpAirToAir,
1638
+ HPXML::HVACTypeHeatPumpMiniSplit,
1639
+ HPXML::HVACTypeMiniSplitAirConditioner,
1640
+ HPXML::HVACTypeHeatPumpGroundToAir].include? hvac.CoolType
1641
+ return if (hvac.ChargeDefectRatio.to_f.abs < 0.001) && (hvac.AirflowDefectRatioCooling.to_f.abs < 0.001) && (hvac.AirflowDefectRatioHeating.to_f.abs < 0.001)
1642
+
1643
+ tin_cool = UnitConversions.convert(@cool_setpoint, 'F', 'C')
1644
+ tin_heat = UnitConversions.convert(@heat_setpoint, 'F', 'C')
1645
+
1646
+ tout_cool = UnitConversions.convert(weather.design.CoolingDrybulb, 'F', 'C')
1647
+ tout_heat = UnitConversions.convert(weather.design.HeatingDrybulb, 'F', 'C')
1648
+
1649
+ if hvac.CoolType == HPXML::HVACTypeHeatPumpGroundToAir
1650
+ if hvac.CoolingLoadFraction > 0
1651
+ # Cooling
1652
+ coil_bf = gshp_coil_bf
1653
+ # Calculate curve point w/ and w/o defect ratios
1654
+ design_wb_temp = UnitConversions.convert(@wetbulb_indoor_cooling, 'f', 'k')
1655
+ design_db_temp = UnitConversions.convert(@cool_setpoint, 'f', 'k')
1656
+ design_w_temp = UnitConversions.convert(hvac.GSHP_design_chw, 'f', 'k')
1657
+ design_vfr_air = UnitConversions.convert(hvac_sizing_values.Cool_Airflow, 'cfm', 'm^3/s')
1658
+ design_vfr_air_defect = UnitConversions.convert(hvac_sizing_values.Cool_Airflow, 'cfm', 'm^3/s') * (1 + hvac.AirflowDefectRatioCooling)
1659
+ # calculate water flow based on current capacity.
1660
+ loop_flow = [1.0, UnitConversions.convert([hvac_sizing_values.Heat_Capacity, hvac_sizing_values.Cool_Capacity].max, 'Btu/hr', 'ton')].max.floor * 3.0
1661
+ loop_flow_m3s = UnitConversions.convert(loop_flow, 'gal/min', 'm^3/s')
1662
+
1663
+ totalCap_CurveValue, sensibleCap_CurveValue = calc_gshp_clg_curve_value(hvac, design_wb_temp, design_db_temp, design_w_temp, design_vfr_air, loop_flow_m3s)
1664
+ totalCap_CurveValue_d, sensibleCap_CurveValue_d = calc_gshp_clg_curve_value(hvac, design_wb_temp, design_db_temp, design_w_temp, design_vfr_air_defect, loop_flow_m3s)
1665
+
1666
+ cap_clg_ratio = 1 / (totalCap_CurveValue_d / totalCap_CurveValue)
1667
+ if cap_clg_ratio > 1
1668
+ hvac_sizing_values.Cool_Capacity *= cap_clg_ratio
1669
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1670
+ bypassFactor_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, @cool_setpoint, gshp_coil_bf_ft_spec)
1671
+
1672
+ cool_Load_SensCap_Design = (hvac_sizing_values.Cool_Capacity_Sens * sensibleCap_CurveValue /
1673
+ (1.0 + (1.0 - coil_bf * bypassFactor_CurveValue) *
1674
+ (80.0 - @cool_setpoint) / (@cool_setpoint - hvac.LeavingAirTemp)))
1675
+ hvac_sizing_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
1676
+ end
1677
+ end
1678
+
1679
+ # Heating
1680
+ if hvac.HeatingLoadFraction > 0
1681
+ # Calculate curve point w/ and w/o defect ratios
1682
+ design_db_temp = UnitConversions.convert(@heat_setpoint, 'f', 'k')
1683
+ design_w_temp = UnitConversions.convert(hvac.GSHP_design_chw, 'f', 'k')
1684
+ design_vfr_air = UnitConversions.convert(hvac_sizing_values.Heat_Airflow, 'cfm', 'm^3/s')
1685
+ design_vfr_air_defect = UnitConversions.convert(hvac_sizing_values.Heat_Airflow, 'cfm', 'm^3/s') * (1 + hvac.AirflowDefectRatioHeating)
1686
+ # calculate water flow based on current capacity.
1687
+ loop_flow = [1.0, UnitConversions.convert([hvac_sizing_values.Heat_Capacity, hvac_sizing_values.Cool_Capacity].max, 'Btu/hr', 'ton')].max.floor * 3.0
1688
+ loop_flow_m3s = UnitConversions.convert(loop_flow, 'gal/min', 'm^3/s')
1689
+
1690
+ totalCap_CurveValue = calc_gshp_htg_curve_value(hvac, design_db_temp, design_w_temp, design_vfr_air, loop_flow_m3s)
1691
+ totalCap_CurveValue_d = calc_gshp_htg_curve_value(hvac, design_db_temp, design_w_temp, design_vfr_air_defect, loop_flow_m3s)
1692
+
1693
+ cap_htg_ratio = 1 / (totalCap_CurveValue_d / totalCap_CurveValue)
1694
+ if cap_htg_ratio > 1
1695
+ hvac_sizing_values.Heat_Capacity *= cap_htg_ratio
1696
+ hvac_sizing_values.Heat_Airflow = calc_airflow_rate(hvac_sizing_values.Heat_Capacity, (hvac.SupplyAirTemp - @heat_setpoint))
1697
+ end
1698
+ end
1699
+ else
1700
+ f_ch = hvac.ChargeDefectRatio.round(3)
1701
+
1702
+ # Cooling
1703
+ if [HPXML::HVACTypeHeatPumpAirToAir,
1704
+ HPXML::HVACTypeCentralAirConditioner,
1705
+ HPXML::HVACTypeHeatPumpMiniSplit,
1706
+ HPXML::HVACTypeMiniSplitAirConditioner].include?(hvac.CoolType) && hvac.CoolingLoadFraction > 0
1707
+ cool_airflow_rated_defect_ratio = []
1708
+ cool_airflow_rated_ratio = []
1709
+ cool_cfm_m3s = UnitConversions.convert(hvac_sizing_values.Cool_Airflow, 'cfm', 'm^3/s')
1710
+ for speed in 0..(hvac.NumSpeedsCooling - 1)
1711
+ cool_airflow_rated_ratio << cool_cfm_m3s / HVAC.calc_rated_airflow(hvac_sizing_values.Cool_Capacity, hvac.RatedCFMperTonCooling[speed], hvac.CapacityRatioCooling[speed])
1712
+ cool_airflow_rated_defect_ratio << cool_cfm_m3s * (1 + hvac.AirflowDefectRatioCooling) / HVAC.calc_rated_airflow(hvac_sizing_values.Cool_Capacity, hvac.RatedCFMperTonCooling[speed], hvac.CapacityRatioCooling[speed])
1713
+ end
1714
+ if not cool_airflow_rated_defect_ratio.empty?
1715
+ cap_clg_ratios = []
1716
+ for speed in 0..(hvac.NumSpeedsCooling - 1)
1717
+ # NOTE: heat pump (cooling) curves don't exhibit expected trends at extreme faults;
1718
+ a1_AF_Qgr_c = hvac.COOL_CAP_FFLOW_SPEC[speed][0]
1719
+ a2_AF_Qgr_c = hvac.COOL_CAP_FFLOW_SPEC[speed][1]
1720
+ a3_AF_Qgr_c = hvac.COOL_CAP_FFLOW_SPEC[speed][2]
1721
+
1722
+ p_values, qgr_values, ff_chg_values = HVAC.get_installation_quality_cooling_coeff(f_ch)
1723
+
1724
+ a1_CH_Qgr_c = qgr_values[0]
1725
+ a2_CH_Qgr_c = qgr_values[1]
1726
+ a3_CH_Qgr_c = qgr_values[2]
1727
+ a4_CH_Qgr_c = qgr_values[3]
1728
+
1729
+ 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_ch)) * f_ch)).round(3)
1730
+
1731
+ q0_CH = a1_CH_Qgr_c
1732
+ q1_CH = a2_CH_Qgr_c * tin_cool
1733
+ q2_CH = a3_CH_Qgr_c * tout_cool
1734
+ q3_CH = a4_CH_Qgr_c * f_ch
1735
+ y_CH_Q_c = 1 + ((q0_CH + q1_CH + q2_CH + q3_CH) * f_ch)
1736
+
1737
+ q0_AF_CH = a1_AF_Qgr_c
1738
+ q1_AF_CH = a2_AF_Qgr_c * ff_ch_c
1739
+ q2_AF_CH = a3_AF_Qgr_c * ff_ch_c * ff_ch_c
1740
+ p_CH_Q_c = y_CH_Q_c / (q0_AF_CH + q1_AF_CH + q2_AF_CH)
1741
+
1742
+ ff_AF_c = cool_airflow_rated_defect_ratio[speed].round(3)
1743
+ ff_AF_c_nodefect = cool_airflow_rated_ratio[speed].round(3)
1744
+ ff_AF_comb_c = ff_ch_c * ff_AF_c
1745
+
1746
+ q0_AF_comb = a1_AF_Qgr_c
1747
+ q1_AF_comb = a2_AF_Qgr_c * ff_AF_comb_c
1748
+ q2_AF_comb = a3_AF_Qgr_c * ff_AF_comb_c * ff_AF_comb_c
1749
+ p_AF_Q_c = q0_AF_comb + q1_AF_comb + q2_AF_comb
1750
+
1751
+ cool_cap_fff = (p_CH_Q_c * p_AF_Q_c)
1752
+ cool_cap_fff_nodefect = a1_AF_Qgr_c + a2_AF_Qgr_c * ff_AF_c_nodefect + a3_AF_Qgr_c * ff_AF_c_nodefect * ff_AF_c_nodefect
1753
+ cap_clg_ratio = 1 / (cool_cap_fff / cool_cap_fff_nodefect)
1754
+ cap_clg_ratios << cap_clg_ratio
1755
+ end
1756
+ prev_capacity = hvac_sizing_values.Cool_Capacity
1757
+ hvac_sizing_values.Cool_Capacity *= cap_clg_ratios.max
1758
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1759
+ if prev_capacity > 0 # Preserve cfm/ton
1760
+ hvac_sizing_values.Cool_Airflow = hvac_sizing_values.Cool_Airflow * hvac_sizing_values.Cool_Capacity / prev_capacity
1761
+ else
1762
+ hvac_sizing_values.Cool_Airflow = 0.0
1763
+ end
1764
+ end
1765
+ end
1766
+
1767
+ # Heating
1768
+ if [HPXML::HVACTypeHeatPumpAirToAir,
1769
+ HPXML::HVACTypeHeatPumpMiniSplit].include?(hvac.HeatType) && hvac.HeatingLoadFraction > 0
1770
+ heat_airflow_rated_defect_ratio = []
1771
+ heat_airflow_rated_ratio = []
1772
+ heat_cfm_m3s = UnitConversions.convert(hvac_sizing_values.Heat_Airflow, 'cfm', 'm^3/s')
1773
+ for speed in 0..(hvac.NumSpeedsHeating - 1)
1774
+ heat_airflow_rated_ratio << heat_cfm_m3s / HVAC.calc_rated_airflow(hvac_sizing_values.Heat_Capacity, hvac.RatedCFMperTonHeating[speed], hvac.CapacityRatioHeating[speed])
1775
+ heat_airflow_rated_defect_ratio << heat_cfm_m3s * (1 + hvac.AirflowDefectRatioHeating) / HVAC.calc_rated_airflow(hvac_sizing_values.Heat_Capacity, hvac.RatedCFMperTonHeating[speed], hvac.CapacityRatioHeating[speed])
1776
+ end
1777
+ if not heat_airflow_rated_defect_ratio.empty?
1778
+ cap_htg_ratios = []
1779
+ for speed in 0..(hvac.NumSpeedsHeating - 1)
1780
+ a1_AF_Qgr_h = hvac.HEAT_CAP_FFLOW_SPEC[speed][0]
1781
+ a2_AF_Qgr_h = hvac.HEAT_CAP_FFLOW_SPEC[speed][1]
1782
+ a3_AF_Qgr_h = hvac.HEAT_CAP_FFLOW_SPEC[speed][2]
1783
+
1784
+ p_values, qgr_values, ff_chg_values = HVAC.get_installation_quality_heating_coeff(f_ch)
1785
+
1786
+ a1_CH_Qgr_h = qgr_values[0]
1787
+ a2_CH_Qgr_h = qgr_values[1]
1788
+ a3_CH_Qgr_h = qgr_values[2]
1789
+
1790
+ ff_ch_h = (1 / (1 + (qgr_values[0] + qgr_values[1] * ff_chg_values[0] + qgr_values[2] * f_ch) * f_ch)).round(3)
1791
+
1792
+ qh1_CH = a1_CH_Qgr_h
1793
+ qh2_CH = a2_CH_Qgr_h * tout_heat
1794
+ qh3_CH = a3_CH_Qgr_h * f_ch
1795
+ y_CH_Q_h = 1 + ((qh1_CH + qh2_CH + qh3_CH) * f_ch)
1796
+
1797
+ qh0_AF_CH = a1_AF_Qgr_h
1798
+ qh1_AF_CH = a2_AF_Qgr_h * ff_ch_h
1799
+ qh2_AF_CH = a3_AF_Qgr_h * ff_ch_h * ff_ch_h
1800
+ p_CH_Q_h = y_CH_Q_h / (qh0_AF_CH + qh1_AF_CH + qh2_AF_CH)
1801
+
1802
+ ff_AF_h = heat_airflow_rated_defect_ratio[speed].round(3)
1803
+ ff_AF_h_nodefect = heat_airflow_rated_ratio[speed].round(3)
1804
+ ff_AF_comb_h = ff_ch_h * ff_AF_h
1805
+
1806
+ qh0_AF_comb = a1_AF_Qgr_h
1807
+ qh1_AF_comb = a2_AF_Qgr_h * ff_AF_comb_h
1808
+ qh2_AF_comb = a3_AF_Qgr_h * ff_AF_comb_h * ff_AF_comb_h
1809
+ p_AF_Q_h = qh0_AF_comb + qh1_AF_comb + qh2_AF_comb
1810
+
1811
+ heat_cap_fff = (p_CH_Q_h * p_AF_Q_h)
1812
+ heat_cap_fff_nodefect = a1_AF_Qgr_h + a2_AF_Qgr_h * ff_AF_h_nodefect + a3_AF_Qgr_h * ff_AF_h_nodefect * ff_AF_h_nodefect
1813
+ cap_htg_ratio = 1 / (heat_cap_fff / heat_cap_fff_nodefect)
1814
+ cap_htg_ratios << cap_htg_ratio
1815
+ end
1816
+ prev_capacity = hvac_sizing_values.Heat_Capacity
1817
+ hvac_sizing_values.Heat_Capacity *= cap_htg_ratios.max
1818
+ if prev_capacity > 0 # Preserve cfm/ton
1819
+ hvac_sizing_values.Heat_Airflow = hvac_sizing_values.Heat_Airflow * hvac_sizing_values.Heat_Capacity / prev_capacity
1820
+ else
1821
+ hvac_sizing_values.Heat_Airflow = 0.0
1822
+ end
1823
+ end
1824
+ end
1825
+ end
1826
+ end
1827
+
1828
+ def self.apply_hvac_fixed_capacities(hvac_sizing_values, hvac)
1516
1829
  '''
1517
1830
  Fixed Sizing Equipment
1518
1831
  '''
1519
1832
 
1520
1833
  # Override HVAC capacities if values are provided
1521
- if not hvac.FixedCoolingCapacity.nil?
1522
- prev_capacity = hvac_final_values.Cool_Capacity
1523
- hvac_final_values.Cool_Capacity = hvac.FixedCoolingCapacity
1834
+ if (not hvac.FixedCoolingCapacity.nil?) && (hvac_sizing_values.Cool_Capacity > 0)
1835
+ prev_capacity = hvac_sizing_values.Cool_Capacity
1836
+ hvac_sizing_values.Cool_Capacity = hvac.FixedCoolingCapacity
1524
1837
  if @hpxml.header.allow_increased_fixed_capacities
1525
- hvac_final_values.Cool_Capacity = [hvac_final_values.Cool_Capacity, prev_capacity].max
1526
- end
1527
- hvac_final_values.Cool_Capacity_Sens = hvac_final_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
1528
- if prev_capacity > 0 # Preserve cfm/ton
1529
- hvac_final_values.Cool_Airflow = hvac_final_values.Cool_Airflow * hvac_final_values.Cool_Capacity / prev_capacity
1530
- else
1531
- hvac_final_values.Cool_Airflow = 0.0
1838
+ hvac_sizing_values.Cool_Capacity = [hvac_sizing_values.Cool_Capacity, prev_capacity].max
1532
1839
  end
1840
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity_Sens * hvac_sizing_values.Cool_Capacity / prev_capacity
1841
+ hvac_sizing_values.Cool_Airflow = hvac_sizing_values.Cool_Airflow * hvac_sizing_values.Cool_Capacity / prev_capacity
1533
1842
  end
1534
- if not hvac.FixedHeatingCapacity.nil?
1535
- prev_capacity = hvac_final_values.Heat_Capacity
1536
- hvac_final_values.Heat_Capacity = hvac.FixedHeatingCapacity
1843
+ if (not hvac.FixedHeatingCapacity.nil?) && (hvac_sizing_values.Heat_Capacity > 0)
1844
+ prev_capacity = hvac_sizing_values.Heat_Capacity
1845
+ hvac_sizing_values.Heat_Capacity = hvac.FixedHeatingCapacity
1537
1846
  if @hpxml.header.allow_increased_fixed_capacities
1538
- hvac_final_values.Heat_Capacity = [hvac_final_values.Heat_Capacity, prev_capacity].max
1539
- end
1540
- if prev_capacity > 0 # Preserve cfm/ton
1541
- hvac_final_values.Heat_Airflow = hvac_final_values.Heat_Airflow * hvac_final_values.Heat_Capacity / prev_capacity
1542
- else
1543
- hvac_final_values.Heat_Airflow = 0.0
1847
+ hvac_sizing_values.Heat_Capacity = [hvac_sizing_values.Heat_Capacity, prev_capacity].max
1544
1848
  end
1849
+ hvac_sizing_values.Heat_Airflow = hvac_sizing_values.Heat_Airflow * hvac_sizing_values.Heat_Capacity / prev_capacity
1545
1850
  end
1546
- if not hvac.FixedSuppHeatingCapacity.nil?
1547
- prev_capacity = hvac_final_values.Heat_Capacity_Supp
1548
- hvac_final_values.Heat_Capacity_Supp = hvac.FixedSuppHeatingCapacity
1851
+ if (not hvac.FixedSuppHeatingCapacity.nil?) && (hvac_sizing_values.Heat_Capacity_Supp > 0)
1852
+ prev_capacity = hvac_sizing_values.Heat_Capacity_Supp
1853
+ hvac_sizing_values.Heat_Capacity_Supp = hvac.FixedSuppHeatingCapacity
1549
1854
  if @hpxml.header.allow_increased_fixed_capacities
1550
- hvac_final_values.Heat_Capacity_Supp = [hvac_final_values.Heat_Capacity_Supp, prev_capacity].max
1855
+ hvac_sizing_values.Heat_Capacity_Supp = [hvac_sizing_values.Heat_Capacity_Supp, prev_capacity].max
1551
1856
  end
1552
1857
  end
1553
1858
  end
1554
1859
 
1555
- def self.process_ground_loop(hvac_final_values, weather, hvac)
1860
+ def self.apply_hvac_ground_loop(hvac_sizing_values, weather, hvac)
1556
1861
  '''
1557
1862
  GSHP Ground Loop Sizing Calculations
1558
1863
  '''
1559
- if hvac.has_type(Constants.ObjectNameGroundSourceHeatPump)
1560
- ground_conductivity = UnitConversions.convert(hvac.GSHP_HXVertical.groundThermalConductivity.get, 'W/(m*K)', 'Btu/(hr*ft*R)')
1561
- grout_conductivity = UnitConversions.convert(hvac.GSHP_HXVertical.groutThermalConductivity.get, 'W/(m*K)', 'Btu/(hr*ft*R)')
1562
- bore_diameter = UnitConversions.convert(hvac.GSHP_HXVertical.boreHoleRadius.get * 2.0, 'm', 'in')
1563
- pipe_od = UnitConversions.convert(hvac.GSHP_HXVertical.pipeOutDiameter.get, 'm', 'in')
1564
- pipe_id = pipe_od - UnitConversions.convert(hvac.GSHP_HXVertical.pipeThickness.get * 2.0, 'm', 'in')
1565
- pipe_cond = UnitConversions.convert(hvac.GSHP_HXVertical.pipeThermalConductivity.get, 'W/(m*K)', 'Btu/(hr*ft*R)')
1566
- pipe_r_value = gshp_hx_pipe_rvalue(pipe_od, pipe_id, pipe_cond)
1567
-
1568
- # Autosize ground loop heat exchanger length
1569
- nom_length_heat, nom_length_cool = gshp_hxbore_ft_per_ton(weather, hvac.GSHP_BoreSpacing, ground_conductivity, hvac.GSHP_SpacingType, grout_conductivity, bore_diameter, pipe_od, pipe_r_value, hvac.HeatingEIR, hvac.CoolingEIR, hvac.GSHP_HXCHWDesign, hvac.GSHP_HXHWDesign, hvac.GSHP_HXDTDesign)
1570
-
1571
- bore_length_heat = nom_length_heat * hvac_final_values.Heat_Capacity / UnitConversions.convert(1.0, 'ton', 'Btu/hr')
1572
- bore_length_cool = nom_length_cool * hvac_final_values.Cool_Capacity / UnitConversions.convert(1.0, 'ton', 'Btu/hr')
1573
- bore_length = [bore_length_heat, bore_length_cool].max
1574
-
1575
- loop_flow = [1.0, UnitConversions.convert([hvac_final_values.Heat_Capacity, hvac_final_values.Cool_Capacity].max, 'Btu/hr', 'ton')].max.floor * 3.0
1576
-
1577
- if hvac.GSHP_BoreHoles.nil? && hvac.GSHP_BoreDepth.nil?
1578
- hvac.GSHP_BoreHoles = [1, (UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'ton') + 0.5).floor].max
1579
- hvac.GSHP_BoreDepth = (bore_length / hvac.GSHP_BoreHoles).floor
1580
- min_bore_depth = 0.15 * hvac.GSHP_BoreSpacing # 0.15 is the maximum Spacing2DepthRatio defined for the G-function
1581
-
1582
- (0..4).to_a.each do |tmp|
1583
- if (hvac.GSHP_BoreDepth < min_bore_depth) && (hvac.GSHP_BoreHoles > 1)
1584
- hvac.GSHP_BoreHoles -= 1
1585
- hvac.GSHP_BoreDepth = (bore_length / hvac.GSHP_BoreHoles).floor
1586
- elsif hvac.GSHP_BoreDepth > 345
1587
- hvac.GSHP_BoreHoles += 1
1588
- hvac.GSHP_BoreDepth = (bore_length / hvac.GSHP_BoreHoles).floor
1589
- end
1590
- end
1591
-
1592
- hvac.GSHP_BoreDepth = (bore_length / hvac.GSHP_BoreHoles).floor + 5
1593
-
1594
- elsif hvac.GSHP_BoreHoles.nil? && (not hvac.GSHP_BoreDepth.nil?)
1595
- hvac.GSHP_BoreHoles = (bore_length / hvac.GSHP_BoreDepth.to_f + 0.5).floor
1596
- hvac.GSHP_BoreDepth = hvac.GSHP_BoreDepth.to_f
1597
- elsif (not hvac.GSHP_BoreHoles.nil?) && hvac.GSHP_BoreDepth.nil?
1598
- hvac.GSHP_BoreHoles = hvac.GSHP_BoreHoles.to_f
1599
- hvac.GSHP_BoreDepth = (bore_length / hvac.GSHP_BoreHoles).floor + 5
1864
+ return unless hvac.CoolType == HPXML::HVACTypeHeatPumpGroundToAir
1865
+
1866
+ # Autosize ground loop heat exchanger length
1867
+ bore_spacing = 20.0 # ft, distance between bores
1868
+ pipe_r_value = gshp_hx_pipe_rvalue(hvac)
1869
+ nom_length_heat, nom_length_cool = gshp_hxbore_ft_per_ton(weather, hvac, bore_spacing, pipe_r_value)
1870
+
1871
+ bore_length_heat = nom_length_heat * hvac_sizing_values.Heat_Capacity / UnitConversions.convert(1.0, 'ton', 'Btu/hr')
1872
+ bore_length_cool = nom_length_cool * hvac_sizing_values.Cool_Capacity / UnitConversions.convert(1.0, 'ton', 'Btu/hr')
1873
+ bore_length = [bore_length_heat, bore_length_cool].max
1874
+
1875
+ loop_flow = [1.0, UnitConversions.convert([hvac_sizing_values.Heat_Capacity, hvac_sizing_values.Cool_Capacity].max, 'Btu/hr', 'ton')].max.floor * 3.0
1876
+
1877
+ num_bore_holes = [1, (UnitConversions.convert(hvac_sizing_values.Cool_Capacity, 'Btu/hr', 'ton') + 0.5).floor].max
1878
+ bore_depth = (bore_length / num_bore_holes).floor # ft
1879
+ min_bore_depth = 0.15 * bore_spacing # 0.15 is the maximum Spacing2DepthRatio defined for the G-function
1880
+
1881
+ (0..4).to_a.each do |tmp|
1882
+ if (bore_depth < min_bore_depth) && (num_bore_holes > 1)
1883
+ num_bore_holes -= 1
1884
+ bore_depth = (bore_length / num_bore_holes).floor
1885
+ elsif bore_depth > 345
1886
+ num_bore_holes += 1
1887
+ bore_depth = (bore_length / num_bore_holes).floor
1888
+ end
1889
+ end
1890
+
1891
+ bore_depth = (bore_length / num_bore_holes).floor + 5
1892
+
1893
+ bore_length = bore_depth * num_bore_holes
1894
+
1895
+ if num_bore_holes == 1
1896
+ bore_config = 'single'
1897
+ elsif num_bore_holes == 2
1898
+ bore_config = 'line'
1899
+ elsif num_bore_holes == 3
1900
+ bore_config = 'line'
1901
+ elsif num_bore_holes == 4
1902
+ bore_config = 'rectangle'
1903
+ elsif num_bore_holes == 5
1904
+ bore_config = 'u-config'
1905
+ elsif num_bore_holes > 5
1906
+ bore_config = 'line'
1907
+ end
1908
+
1909
+ # Test for valid GSHP bore field configurations
1910
+ valid_configs = { 'single' => [1],
1911
+ 'line' => [2, 3, 4, 5, 6, 7, 8, 9, 10],
1912
+ 'l-config' => [3, 4, 5, 6],
1913
+ 'rectangle' => [2, 4, 6, 8],
1914
+ 'u-config' => [5, 7, 9],
1915
+ 'l2-config' => [8],
1916
+ 'open-rectangle' => [8] }
1917
+ valid_num_bores = valid_configs[bore_config]
1918
+ max_valid_configs = { 'line' => 10, 'l-config' => 6 }
1919
+ unless valid_num_bores.include? num_bore_holes
1920
+ # Any configuration with a max_valid_configs value can accept any number of bores up to the maximum
1921
+ if max_valid_configs.keys.include? bore_config
1922
+ max_num_bore_holes = max_valid_configs[bore_config]
1923
+ num_bore_holes = max_num_bore_holes
1600
1924
  else
1601
- @runner.registerWarning('User is hard sizing the bore field, improper sizing may lead to unbalanced / unsteady ground loop temperature and erroneous prediction of system energy related cost.')
1602
- hvac.GSHP_BoreHoles = hvac.GSHP_BoreHoles.to_f
1603
- hvac.GSHP_BoreDepth = hvac.GSHP_BoreDepth.to_f
1604
- end
1605
-
1606
- bore_length = hvac.GSHP_BoreDepth * hvac.GSHP_BoreHoles
1607
-
1608
- if hvac.GSHP_BoreConfig.nil?
1609
- if hvac.GSHP_BoreHoles == 1
1610
- hvac.GSHP_BoreConfig = Constants.BoreConfigSingle
1611
- elsif hvac.GSHP_BoreHoles == 2
1612
- hvac.GSHP_BoreConfig = Constants.BoreConfigLine
1613
- elsif hvac.GSHP_BoreHoles == 3
1614
- hvac.GSHP_BoreConfig = Constants.BoreConfigLine
1615
- elsif hvac.GSHP_BoreHoles == 4
1616
- hvac.GSHP_BoreConfig = Constants.BoreConfigRectangle
1617
- elsif hvac.GSHP_BoreHoles == 5
1618
- hvac.GSHP_BoreConfig = Constants.BoreConfigUconfig
1619
- elsif hvac.GSHP_BoreHoles > 5
1620
- hvac.GSHP_BoreConfig = Constants.BoreConfigLine
1621
- end
1622
- end
1623
-
1624
- # Test for valid GSHP bore field configurations
1625
- valid_configs = { Constants.BoreConfigSingle => [1],
1626
- Constants.BoreConfigLine => [2, 3, 4, 5, 6, 7, 8, 9, 10],
1627
- Constants.BoreConfigLconfig => [3, 4, 5, 6],
1628
- Constants.BoreConfigRectangle => [2, 4, 6, 8],
1629
- Constants.BoreConfigUconfig => [5, 7, 9],
1630
- Constants.BoreConfigL2config => [8],
1631
- Constants.BoreConfigOpenRectangle => [8] }
1632
- valid_num_bores = valid_configs[hvac.GSHP_BoreConfig]
1633
- max_valid_configs = { Constants.BoreConfigLine => 10, Constants.BoreConfigLconfig => 6 }
1634
- unless valid_num_bores.include? hvac.GSHP_BoreHoles
1635
- # Any configuration with a max_valid_configs value can accept any number of bores up to the maximum
1636
- if max_valid_configs.keys.include? hvac.GSHP_BoreConfig
1637
- max_bore_holes = max_valid_configs[hvac.GSHP_BoreConfig]
1638
- @runner.registerWarning("Maximum number of bore holes for '#{hvac.GSHP_BoreConfig}' bore configuration is #{max_bore_holes}. Overriding value of #{hvac.GSHP_BoreHoles} bore holes to #{max_bore_holes}.")
1639
- hvac.GSHP_BoreHoles = max_bore_holes
1925
+ # Search for first valid bore field
1926
+ new_bore_config = nil
1927
+ valid_field_found = false
1928
+ valid_configs.keys.each do |bore_config|
1929
+ next unless valid_configs[bore_config].include? num_bore_holes
1930
+
1931
+ valid_field_found = true
1932
+ new_bore_config = bore_config
1933
+ break
1934
+ end
1935
+ if valid_field_found
1936
+ bore_config = new_bore_config
1640
1937
  else
1641
- # Search for first valid bore field
1642
- new_bore_config = nil
1643
- valid_field_found = false
1644
- valid_configs.keys.each do |bore_config|
1645
- next unless valid_configs[bore_config].include? hvac.GSHP_BoreHoles
1646
-
1647
- valid_field_found = true
1648
- new_bore_config = bore_config
1649
- break
1650
- end
1651
- if valid_field_found
1652
- @runner.registerWarning("Bore field '#{hvac.GSHP_BoreConfig}' with #{hvac.GSHP_BoreHoles.to_i} bore holes is an invalid configuration. Changing layout to '#{new_bore_config}' configuration.")
1653
- hvac.GSHP_BoreConfig = new_bore_config
1654
- else
1655
- fail 'Could not construct a valid GSHP bore field configuration.'
1656
- end
1938
+ fail 'Could not construct a valid GSHP bore field configuration.'
1657
1939
  end
1658
1940
  end
1941
+ end
1659
1942
 
1660
- spacing_to_depth_ratio = hvac.GSHP_BoreSpacing / hvac.GSHP_BoreDepth
1943
+ spacing_to_depth_ratio = bore_spacing / bore_depth
1661
1944
 
1662
- lntts = [-8.5, -7.8, -7.2, -6.5, -5.9, -5.2, -4.5, -3.963, -3.27, -2.864, -2.577, -2.171, -1.884, -1.191, -0.497, -0.274, -0.051, 0.196, 0.419, 0.642, 0.873, 1.112, 1.335, 1.679, 2.028, 2.275, 3.003]
1663
- gfnc_coeff = gshp_gfnc_coeff(hvac.GSHP_BoreConfig, hvac.GSHP_BoreHoles, spacing_to_depth_ratio)
1945
+ lntts = [-8.5, -7.8, -7.2, -6.5, -5.9, -5.2, -4.5, -3.963, -3.27, -2.864, -2.577, -2.171, -1.884, -1.191, -0.497, -0.274, -0.051, 0.196, 0.419, 0.642, 0.873, 1.112, 1.335, 1.679, 2.028, 2.275, 3.003]
1946
+ gfnc_coeff = gshp_gfnc_coeff(bore_config, num_bore_holes, spacing_to_depth_ratio)
1664
1947
 
1665
- hvac_final_values.GSHP_Loop_flow = loop_flow
1666
- hvac_final_values.GSHP_Bore_Depth = hvac.GSHP_BoreDepth
1667
- hvac_final_values.GSHP_Bore_Holes = hvac.GSHP_BoreHoles
1668
- hvac_final_values.GSHP_G_Functions = [lntts, gfnc_coeff]
1669
- end
1948
+ hvac_sizing_values.GSHP_Loop_flow = loop_flow
1949
+ hvac_sizing_values.GSHP_Bore_Depth = bore_depth
1950
+ hvac_sizing_values.GSHP_Bore_Holes = num_bore_holes
1951
+ hvac_sizing_values.GSHP_G_Functions = [lntts, gfnc_coeff]
1670
1952
  end
1671
1953
 
1672
- def self.process_finalize(hvac_final_values, zone_loads, weather, hvac)
1954
+ def self.apply_hvac_finalize_airflows(hvac_sizing_values, weather, hvac)
1673
1955
  '''
1674
1956
  Finalize Sizing Calculations
1675
1957
  '''
1676
1958
 
1677
- # Prevent errors of "has no air flow"
1678
- min_air_flow = 3.0 # cfm; E+ minimum is 0.001 m^3/s"
1679
- if hvac_final_values.Heat_Airflow > 0
1680
- hvac_final_values.Heat_Airflow = [hvac_final_values.Heat_Airflow, min_air_flow].max
1959
+ if hvac_sizing_values.Heat_Airflow > 0
1960
+ hvac_sizing_values.Heat_Airflow *= (1.0 + hvac.AirflowDefectRatioHeating)
1681
1961
  end
1682
- if hvac_final_values.Cool_Airflow > 0
1683
- hvac_final_values.Cool_Airflow = [hvac_final_values.Cool_Airflow, min_air_flow].max
1962
+
1963
+ if hvac_sizing_values.Cool_Airflow > 0
1964
+ hvac_sizing_values.Cool_Airflow *= (1.0 + hvac.AirflowDefectRatioCooling)
1684
1965
  end
1685
1966
  end
1686
1967
 
1687
- def self.process_heat_pump_adjustment(hvac_final_values, weather, hvac, totalCap_CurveValue)
1968
+ def self.process_heat_pump_adjustment(hvac_sizing_values, weather, hvac, totalCap_CurveValue)
1688
1969
  '''
1689
1970
  Adjust heat pump sizing
1690
1971
  '''
@@ -1696,88 +1977,129 @@ class HVACSizing
1696
1977
  capacity_ratio = 1.0
1697
1978
  end
1698
1979
 
1699
- heatCap_Rated = (hvac_final_values.Heat_Load / MathTools.biquadratic(@heat_setpoint, weather.design.HeatingDrybulb, coefficients)) / capacity_ratio
1980
+ heatCap_Rated = (hvac_sizing_values.Heat_Load / MathTools.biquadratic(@heat_setpoint, weather.design.HeatingDrybulb, coefficients)) / capacity_ratio
1700
1981
 
1701
- if heatCap_Rated < hvac_final_values.Cool_Capacity
1702
- if hvac.has_type(Constants.ObjectNameAirSourceHeatPump)
1703
- hvac_final_values.Heat_Capacity = hvac_final_values.Cool_Capacity
1704
- elsif hvac.has_type(Constants.ObjectNameMiniSplitHeatPump)
1705
- hvac_final_values.Heat_Capacity = [hvac_final_values.Cool_Capacity + hvac.HeatingCapacityOffset, Constants.small].max
1706
- end
1707
- else
1708
- cfm_Btu = hvac_final_values.Cool_Airflow / hvac_final_values.Cool_Capacity
1709
- load_shr = hvac_final_values.Cool_Load_Sens / hvac_final_values.Cool_Load_Tot
1982
+ if heatCap_Rated >= hvac_sizing_values.Cool_Capacity
1983
+ cfm_per_btuh = hvac_sizing_values.Cool_Airflow / hvac_sizing_values.Cool_Capacity
1984
+ load_shr = hvac_sizing_values.Cool_Load_Sens / hvac_sizing_values.Cool_Load_Tot
1710
1985
  if ((weather.data.HDD65F / weather.data.CDD50F) < 2.0) || (load_shr < 0.95)
1711
1986
  # Mild winter or has a latent cooling load
1712
- hvac_final_values.Cool_Capacity = [(hvac.OverSizeLimit * hvac_final_values.Cool_Load_Tot) / totalCap_CurveValue, heatCap_Rated].min
1987
+ hvac_sizing_values.Cool_Capacity = [(hvac.OverSizeLimit * hvac_sizing_values.Cool_Load_Tot) / totalCap_CurveValue, heatCap_Rated].min
1713
1988
  else
1714
1989
  # Cold winter and no latent cooling load (add a ton rule applies)
1715
- hvac_final_values.Cool_Capacity = [(hvac_final_values.Cool_Load_Tot + hvac.OverSizeDelta) / totalCap_CurveValue, heatCap_Rated].min
1990
+ hvac_sizing_values.Cool_Capacity = [(hvac_sizing_values.Cool_Load_Tot + hvac.OverSizeDelta) / totalCap_CurveValue, heatCap_Rated].min
1716
1991
  end
1717
- if hvac.has_type(Constants.ObjectNameAirSourceHeatPump)
1718
- hvac_final_values.Cool_Airflow = cfm_Btu * hvac_final_values.Cool_Capacity
1719
- hvac_final_values.Heat_Capacity = hvac_final_values.Cool_Capacity
1720
- elsif hvac.has_type(Constants.ObjectNameMiniSplitHeatPump)
1721
- hvac_final_values.Cool_Airflow = hvac.RatedCFMperTonCooling[-1] * UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'ton')
1722
- hvac_final_values.Heat_Capacity = [hvac_final_values.Cool_Capacity + hvac.HeatingCapacityOffset, Constants.small].max
1992
+ if hvac.HeatType == HPXML::HVACTypeHeatPumpAirToAir
1993
+ hvac_sizing_values.Cool_Airflow = cfm_per_btuh * hvac_sizing_values.Cool_Capacity
1994
+ elsif hvac.HeatType == HPXML::HVACTypeHeatPumpMiniSplit
1995
+ hvac_sizing_values.Cool_Airflow = hvac.RatedCFMperTonCooling[-1] * hvac.CapacityRatioCooling[-1] * UnitConversions.convert(hvac_sizing_values.Cool_Capacity, 'Btu/hr', 'ton')
1723
1996
  end
1724
1997
  end
1725
-
1726
- return hvac_final_values
1727
1998
  end
1728
1999
 
1729
- def self.get_shelter_class(model, min_neighbor_distance)
1730
- height_ft = Geometry.get_height_of_spaces([@spaces[HPXML::LocationLivingSpace]])
1731
- tot_cb_area, ext_cb_area = @hpxml.compartmentalization_boundary_areas()
1732
- exposed_wall_ratio = ext_cb_area / tot_cb_area
1733
-
1734
- if exposed_wall_ratio > 0.5 # 3 or 4 exposures; Table 5D
1735
- if min_neighbor_distance.nil?
1736
- shelter_class = 2 # Typical shelter for isolated rural house
1737
- elsif min_neighbor_distance > height_ft
1738
- shelter_class = 3 # Typical shelter caused by other buildings across the street
1739
- else
1740
- shelter_class = 4 # Typical shelter for urban buildings where sheltering obstacles are less than one building height away
1741
- end
1742
- else # 0, 1, or 2 exposures; Table 5E
1743
- if min_neighbor_distance.nil?
1744
- if exposed_wall_ratio > 0.25 # 2 exposures; Table 5E
1745
- shelter_class = 2 # Typical shelter for isolated rural house
1746
- else # 1 exposure; Table 5E
1747
- shelter_class = 3 # Typical shelter caused by other buildings across the street
1748
- end
1749
- elsif min_neighbor_distance > height_ft
1750
- shelter_class = 4 # Typical shelter for urban buildings where sheltering obstacles are less than one building height away
1751
- else
1752
- shelter_class = 5 # Typical shelter for urban buildings where sheltering obstacles are less than one building height away
1753
- end
2000
+ def self.get_ventilation_rates()
2001
+ vent_fans_mech = @hpxml.ventilation_fans.select { |f| f.used_for_whole_building_ventilation }
2002
+ if vent_fans_mech.empty?
2003
+ return [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
1754
2004
  end
1755
2005
 
1756
- return shelter_class
1757
- end
2006
+ # Categorize fans into different types
2007
+ vent_mech_preheat = vent_fans_mech.select { |vent_mech| (not vent_mech.preheating_efficiency_cop.nil?) }
2008
+ vent_mech_precool = vent_fans_mech.select { |vent_mech| (not vent_mech.precooling_efficiency_cop.nil?) }
2009
+ vent_mech_shared = vent_fans_mech.select { |vent_mech| vent_mech.is_shared_system }
2010
+
2011
+ vent_mech_sup_tot = vent_fans_mech.select { |vent_mech| vent_mech.fan_type == HPXML::MechVentTypeSupply }
2012
+ vent_mech_exh_tot = vent_fans_mech.select { |vent_mech| vent_mech.fan_type == HPXML::MechVentTypeExhaust }
2013
+ vent_mech_cfis_tot = vent_fans_mech.select { |vent_mech| vent_mech.fan_type == HPXML::MechVentTypeCFIS }
2014
+ vent_mech_bal_tot = vent_fans_mech.select { |vent_mech| vent_mech.fan_type == HPXML::MechVentTypeBalanced }
2015
+ vent_mech_erv_hrv_tot = vent_fans_mech.select { |vent_mech| [HPXML::MechVentTypeERV, HPXML::MechVentTypeHRV].include? vent_mech.fan_type }
2016
+
2017
+ # Average in-unit CFMs (include recirculation from in unit CFMs for shared systems)
2018
+ sup_cfm_tot = vent_mech_sup_tot.map { |vent_mech| vent_mech.average_total_unit_flow_rate }.sum(0.0)
2019
+ exh_cfm_tot = vent_mech_exh_tot.map { |vent_mech| vent_mech.average_total_unit_flow_rate }.sum(0.0)
2020
+ bal_cfm_tot = vent_mech_bal_tot.map { |vent_mech| vent_mech.average_total_unit_flow_rate }.sum(0.0)
2021
+ erv_hrv_cfm_tot = vent_mech_erv_hrv_tot.map { |vent_mech| vent_mech.average_total_unit_flow_rate }.sum(0.0)
2022
+ cfis_cfm_tot = vent_mech_cfis_tot.map { |vent_mech| vent_mech.average_total_unit_flow_rate }.sum(0.0)
2023
+
2024
+ # Average preconditioned OA air CFMs (only OA, recirculation will be addressed below for all shared systems)
2025
+ oa_cfm_preheat = vent_mech_preheat.map { |vent_mech| vent_mech.average_oa_unit_flow_rate * vent_mech.preheating_fraction_load_served }.sum(0.0)
2026
+ oa_cfm_precool = vent_mech_precool.map { |vent_mech| vent_mech.average_oa_unit_flow_rate * vent_mech.precooling_fraction_load_served }.sum(0.0)
2027
+ recirc_cfm_shared = vent_mech_shared.map { |vent_mech| vent_mech.average_total_unit_flow_rate - vent_mech.average_oa_unit_flow_rate }.sum(0.0)
2028
+
2029
+ # Total CFMS
2030
+ tot_sup_cfm = sup_cfm_tot + bal_cfm_tot + erv_hrv_cfm_tot + cfis_cfm_tot
2031
+ tot_exh_cfm = exh_cfm_tot + bal_cfm_tot + erv_hrv_cfm_tot
2032
+ tot_unbal_cfm = (tot_sup_cfm - tot_exh_cfm).abs
2033
+ tot_bal_cfm = [tot_exh_cfm, tot_sup_cfm].min
1758
2034
 
1759
- def self.get_ventilation_rates(model)
1760
- mechVentExist = get_feature(model.getBuilding, Constants.SizingInfoMechVentExist, 'boolean')
1761
- return [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] unless mechVentExist
2035
+ # Calculate effectivenesses for all ERV/HRV and store results in a hash
2036
+ hrv_erv_effectiveness_map = Airflow.calc_hrv_erv_effectiveness(vent_mech_erv_hrv_tot)
1762
2037
 
1763
- q_unb_cfm = get_feature(model.getBuilding, Constants.SizingInfoMechVentWholeHouseRateUnbalanced, 'double')
1764
- q_b = get_feature(model.getBuilding, Constants.SizingInfoMechVentWholeHouseRateBalanced, 'double')
1765
- q_preheat = get_feature(model.getBuilding, Constants.SizingInfoMechVentWholeHouseRatePreHeated, 'double')
1766
- q_precool = get_feature(model.getBuilding, Constants.SizingInfoMechVentWholeHouseRatePreCooled, 'double')
1767
- q_recirc = get_feature(model.getBuilding, Constants.SizingInfoMechVentWholeHouseRateRecirculated, 'double')
1768
- apparentSensibleEffectiveness = get_feature(model.getBuilding, Constants.SizingInfoMechVentApparentSensibleEffectiveness, 'double')
1769
- latentEffectiveness = get_feature(model.getBuilding, Constants.SizingInfoMechVentLatentEffectiveness, 'double')
2038
+ # Calculate cfm weighted average effectivenesses for the combined balanced airflow
2039
+ weighted_vent_mech_lat_eff = 0.0
2040
+ weighted_vent_mech_apparent_sens_eff = 0.0
2041
+ vent_mech_erv_hrv_unprecond = vent_mech_erv_hrv_tot.select { |vent_mech| vent_mech.preheating_efficiency_cop.nil? && vent_mech.precooling_efficiency_cop.nil? }
2042
+ vent_mech_erv_hrv_unprecond.each do |vent_mech|
2043
+ weighted_vent_mech_lat_eff += vent_mech.average_oa_unit_flow_rate / tot_bal_cfm * hrv_erv_effectiveness_map[vent_mech][:vent_mech_lat_eff]
2044
+ weighted_vent_mech_apparent_sens_eff += vent_mech.average_oa_unit_flow_rate / tot_bal_cfm * hrv_erv_effectiveness_map[vent_mech][:vent_mech_apparent_sens_eff]
2045
+ end
1770
2046
 
1771
- q_bal_sens = q_b * (1.0 - apparentSensibleEffectiveness)
1772
- q_bal_lat = q_b * (1.0 - latentEffectiveness)
2047
+ tot_bal_cfm_sens = tot_bal_cfm * (1.0 - weighted_vent_mech_apparent_sens_eff)
2048
+ tot_bal_cfm_lat = tot_bal_cfm * (1.0 - weighted_vent_mech_lat_eff)
1773
2049
 
1774
- return [q_unb_cfm, q_preheat, q_precool, q_recirc, q_bal_sens, q_bal_lat]
2050
+ return [tot_unbal_cfm, oa_cfm_preheat, oa_cfm_precool, recirc_cfm_shared, tot_bal_cfm_sens, tot_bal_cfm_lat]
1775
2051
  end
1776
2052
 
1777
2053
  def self.calc_airflow_rate(load_or_capacity, deltaT)
1778
2054
  return load_or_capacity / (1.1 * @acf * deltaT)
1779
2055
  end
1780
2056
 
2057
+ def self.calc_gshp_clg_curve_value(hvac, wb_temp, db_temp, w_temp, vfr_air, loop_flow)
2058
+ # Reference conditions in thesis with largest capacity:
2059
+ # See Appendix B Figure B.3 of https://hvac.okstate.edu/sites/default/files/pubs/theses/MS/27-Tang_Thesis_05.pdf
2060
+ ref_temp = 283 # K
2061
+ ref_vfr_air = UnitConversions.convert(1200, 'cfm', 'm^3/s')
2062
+ ref_vfr_water = 0.000284
2063
+
2064
+ a_1 = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed][0]
2065
+ a_2 = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed][1]
2066
+ a_3 = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed][2]
2067
+ a_4 = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed][3]
2068
+ a_5 = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed][4]
2069
+ b_1 = hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed][0]
2070
+ b_2 = hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed][1]
2071
+ b_3 = hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed][2]
2072
+ b_4 = hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed][3]
2073
+ b_5 = hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed][4]
2074
+ b_6 = hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed][5]
2075
+
2076
+ if not loop_flow.nil?
2077
+ totalCap_CurveValue = a_1 + wb_temp / ref_temp * a_2 + w_temp / ref_temp * a_3 + vfr_air / ref_vfr_air * a_4 + loop_flow / ref_vfr_water * a_5
2078
+ sensibleCap_CurveValue = b_1 + db_temp / ref_temp * b_2 + wb_temp / ref_temp * b_3 + w_temp / ref_temp * b_4 + vfr_air / ref_vfr_air * b_5 + loop_flow / ref_vfr_water * b_6
2079
+ else
2080
+ totalCap_CurveValue = a_1 + wb_temp / ref_temp * a_2 + w_temp / ref_temp * a_3 + vfr_air / ref_vfr_air * a_4
2081
+ sensibleCap_CurveValue = b_1 + db_temp / ref_temp * b_2 + wb_temp / ref_temp * b_3 + w_temp / ref_temp * b_4 + vfr_air / ref_vfr_air * b_5
2082
+ end
2083
+ return totalCap_CurveValue, sensibleCap_CurveValue
2084
+ end
2085
+
2086
+ def self.calc_gshp_htg_curve_value(hvac, db_temp, w_temp, vfr_air, loop_flow)
2087
+ # Reference conditions in thesis with largest capacity:
2088
+ # See Appendix B Figure B.3 of https://hvac.okstate.edu/sites/default/files/pubs/theses/MS/27-Tang_Thesis_05.pdf
2089
+ ref_temp = 283 # K
2090
+ ref_vfr_air = UnitConversions.convert(1200, 'cfm', 'm^3/s')
2091
+ ref_vfr_water = 0.000284
2092
+
2093
+ a_1 = hvac.HEAT_CAP_FT_SPEC[hvac.SizingSpeed][0]
2094
+ a_2 = hvac.HEAT_CAP_FT_SPEC[hvac.SizingSpeed][1]
2095
+ a_3 = hvac.HEAT_CAP_FT_SPEC[hvac.SizingSpeed][2]
2096
+ a_4 = hvac.HEAT_CAP_FT_SPEC[hvac.SizingSpeed][3]
2097
+ a_5 = hvac.HEAT_CAP_FT_SPEC[hvac.SizingSpeed][4]
2098
+
2099
+ cap_CurveValue = a_1 + db_temp / ref_temp * a_2 + w_temp / ref_temp * a_3 + vfr_air / ref_vfr_air * a_4 + loop_flow / ref_vfr_water * a_5
2100
+ return cap_CurveValue
2101
+ end
2102
+
1781
2103
  def self.calc_delivery_effectiveness_heating(dse_Qs, dse_Qr, system_cfm, load_sens, dse_Tamb_s, dse_Tamb_r, dse_As, dse_Ar, t_setpoint, dse_Fregain_s, dse_Fregain_r, supply_r, return_r, air_dens = @inside_air_dens, air_cp = Gas.Air.cp)
1782
2104
  '''
1783
2105
  Calculate the Delivery Effectiveness for heating (using the method of ASHRAE Standard 152).
@@ -1862,61 +2184,6 @@ class HVACSizing
1862
2184
  return cool_Load_Lat, cool_Load_Sens
1863
2185
  end
1864
2186
 
1865
- def self.get_ducts_for_object(object)
1866
- ducts = []
1867
-
1868
- # Ducted?
1869
- is_ducted = get_feature(object, Constants.SizingInfoHVACSystemIsDucted, 'boolean', false)
1870
- is_ducted = true if is_ducted.nil?
1871
- return ducts if not is_ducted
1872
-
1873
- # Has ducts?
1874
- has_ducts = get_feature(object, Constants.SizingInfoDuctExist, 'boolean', false)
1875
- return ducts if ducts.nil?
1876
-
1877
- # Leakage values
1878
- leakage_fracs = get_feature(object, Constants.SizingInfoDuctLeakageFracs, 'string', false)
1879
- leakage_cfm25s = get_feature(object, Constants.SizingInfoDuctLeakageCFM25s, 'string', false)
1880
- return ducts if leakage_fracs.nil? || leakage_cfm25s.nil?
1881
-
1882
- leakage_fracs = leakage_fracs.split(',').map(&:to_f)
1883
- leakage_cfm25s = leakage_cfm25s.split(',').map(&:to_f)
1884
- if leakage_fracs.sum(0.0) == 0.0
1885
- leakage_fracs = [nil] * leakage_fracs.size
1886
- else
1887
- leakage_cfm25s = [nil] * leakage_cfm25s.size
1888
- end
1889
-
1890
- # Areas
1891
- areas = get_feature(object, Constants.SizingInfoDuctAreas, 'string')
1892
- areas = areas.split(',').map(&:to_f)
1893
-
1894
- # R-values
1895
- rvalues = get_feature(object, Constants.SizingInfoDuctRvalues, 'string')
1896
- rvalues = rvalues.split(',').map(&:to_f)
1897
-
1898
- # Locations
1899
- locations = get_feature(object, Constants.SizingInfoDuctLocations, 'string')
1900
- locations = locations.split(',')
1901
-
1902
- # Sides
1903
- sides = get_feature(object, Constants.SizingInfoDuctSides, 'string')
1904
- sides = sides.split(',')
1905
-
1906
- locations.each_with_index do |location, index|
1907
- d = DuctInfo.new
1908
- d.Location = location
1909
- d.LeakageFrac = leakage_fracs[index]
1910
- d.LeakageCFM25 = leakage_cfm25s[index]
1911
- d.Area = areas[index]
1912
- d.Rvalue = rvalues[index]
1913
- d.Side = sides[index]
1914
- ducts << d
1915
- end
1916
-
1917
- return ducts
1918
- end
1919
-
1920
2187
  def self.calc_ducts_area_weighted_average(ducts, values)
1921
2188
  '''
1922
2189
  Calculate area-weighted average values for unconditioned duct(s)
@@ -1966,9 +2233,9 @@ class HVACSizing
1966
2233
  ducts.each do |duct|
1967
2234
  next if [HPXML::LocationLivingSpace, HPXML::LocationBasementConditioned].include? duct.Location
1968
2235
 
1969
- if not duct.LeakageFrac.nil?
2236
+ if duct.LeakageFrac.to_f > 0
1970
2237
  cfms[duct.Side] += duct.LeakageFrac * system_cfm
1971
- elsif not duct.LeakageCFM25.nil?
2238
+ elsif duct.LeakageCFM25.to_f > 0
1972
2239
  cfms[duct.Side] += duct.LeakageCFM25
1973
2240
  end
1974
2241
  end
@@ -1993,302 +2260,243 @@ class HVACSizing
1993
2260
  return 1.0 / supply_u, 1.0 / return_u
1994
2261
  end
1995
2262
 
1996
- def self.get_hvacs(model)
1997
- hvacs = []
1998
-
1999
- # Get unique set of HVAC equipment
2000
- equips = []
2263
+ def self.get_hvac_information(hvac_system)
2264
+ # FUTURE: Remove this method and use hvac_system objects directly.
2265
+ hvac = HVACInfo.new
2001
2266
 
2002
- HVAC.existing_equipment(model, @cond_zone, @runner).each do |equip|
2003
- next if equips.include? equip
2004
- next if equip.is_a? OpenStudio::Model::ZoneHVACIdealLoadsAirSystem
2005
-
2006
- equips << equip
2267
+ hpxml_hvacs = []
2268
+ if not hvac_system[:heating].nil?
2269
+ hpxml_hvacs << hvac_system[:heating]
2270
+ end
2271
+ if not hvac_system[:cooling].nil?
2272
+ hpxml_hvacs << hvac_system[:cooling]
2007
2273
  end
2008
2274
 
2009
- # Process each equipment
2010
- equips.each do |equip|
2011
- hvac = HVACInfo.new
2012
- hvacs << hvac
2013
-
2014
- hvac.Objects = [equip]
2015
-
2016
- clg_coil, htg_coil, supp_htg_coil = HVAC.get_coils_from_hvac_equip(model, equip)
2017
-
2018
- # Get type of heating/cooling system
2019
- hvac.CoolType = get_feature(equip, Constants.SizingInfoHVACCoolType, 'string', false)
2020
- hvac.HeatType = get_feature(equip, Constants.SizingInfoHVACHeatType, 'string', false)
2021
-
2022
- # Retrieve ducts if they exist
2023
- if equip.is_a? OpenStudio::Model::AirLoopHVACUnitarySystem
2024
- if equip.airLoopHVAC.is_initialized
2025
- hvac.Ducts = get_ducts_for_object(equip.airLoopHVAC.get)
2026
- end
2027
- elsif equip.is_a? OpenStudio::Model::ZoneHVACFourPipeFanCoil
2028
- hvac.Ducts = get_ducts_for_object(equip)
2029
- elsif equip.is_a? OpenStudio::Model::EvaporativeCoolerDirectResearchSpecial
2030
- hvac.Ducts = get_ducts_for_object(equip.airLoopHVAC.get)
2275
+ # Get heating/cooling system info from HPXML objects
2276
+ hpxml_hvacs.uniq.each do |hpxml_hvac|
2277
+ hpxml_hvac_ap = hpxml_hvac.additional_properties
2031
2278
 
2032
- hvac.CoolingLoadFraction = get_feature(equip, Constants.SizingInfoHVACFracCoolLoadServed, 'double')
2033
- hvac.EvapCoolerEffectiveness = equip.coolerEffectiveness
2279
+ # System type
2280
+ if hpxml_hvac.respond_to? :heating_system_type
2281
+ hvac.HeatType = hpxml_hvac.heating_system_type
2282
+ elsif hpxml_hvac.respond_to? :cooling_system_type
2283
+ hvac.CoolType = hpxml_hvac.cooling_system_type
2284
+ elsif hpxml_hvac.respond_to? :heat_pump_type
2285
+ hvac.HeatType = hpxml_hvac.heat_pump_type
2286
+ hvac.CoolType = hpxml_hvac.heat_pump_type
2034
2287
  end
2035
2288
 
2036
- hvac.FanWatts = get_feature(equip, Constants.SizingInfoHVACFanWatts, 'double', false)
2037
- if not clg_coil.nil?
2038
- ratedCFMperTonCooling = get_feature(equip, Constants.SizingInfoHVACRatedCFMperTonCooling, 'string', false)
2039
- if not ratedCFMperTonCooling.nil?
2040
- hvac.RatedCFMperTonCooling = ratedCFMperTonCooling.split(',').map(&:to_f)
2041
- end
2042
-
2043
- hvac.CoolingLoadFraction = get_feature(equip, Constants.SizingInfoHVACFracCoolLoadServed, 'double')
2289
+ # Load fractions
2290
+ if hpxml_hvac.respond_to? :fraction_heat_load_served
2291
+ hvac.HeatingLoadFraction = hpxml_hvac.fraction_heat_load_served
2292
+ end
2293
+ if hpxml_hvac.respond_to? :fraction_cool_load_served
2294
+ hvac.CoolingLoadFraction = hpxml_hvac.fraction_cool_load_served
2044
2295
  end
2045
2296
 
2046
- if clg_coil.is_a? OpenStudio::Model::CoilCoolingDXSingleSpeed
2047
- hvac.NumSpeedsCooling = 1
2048
-
2049
- if hvac.has_type(Constants.ObjectNameRoomAirConditioner)
2050
- ratedCFMperTonCooling = get_feature(equip, Constants.SizingInfoHVACRatedCFMperTonCooling, 'string')
2051
-
2052
- hvac.RatedCFMperTonCooling = ratedCFMperTonCooling.split(',').map(&:to_f)
2053
- end
2054
-
2055
- curves = [clg_coil.totalCoolingCapacityFunctionOfTemperatureCurve]
2056
- hvac.COOL_CAP_FT_SPEC = get_2d_vector_from_CAP_FT_SPEC_curves(curves, hvac.NumSpeedsCooling)
2057
- if not clg_coil.ratedSensibleHeatRatio.is_initialized
2058
- fail "SHR not set for #{clg_coil.name}."
2059
- end
2297
+ # Capacities
2298
+ if hpxml_hvac.respond_to? :heating_capacity
2299
+ hvac.FixedHeatingCapacity = hpxml_hvac.heating_capacity
2300
+ end
2301
+ if hpxml_hvac.respond_to? :cooling_capacity
2302
+ hvac.FixedCoolingCapacity = hpxml_hvac.cooling_capacity
2303
+ end
2304
+ if hpxml_hvac.respond_to? :backup_heating_capacity
2305
+ hvac.FixedSuppHeatingCapacity = hpxml_hvac.backup_heating_capacity
2306
+ end
2060
2307
 
2061
- hvac.SHRRated = [clg_coil.ratedSensibleHeatRatio.get]
2062
- if clg_coil.ratedTotalCoolingCapacity.is_initialized
2063
- hvac.FixedCoolingCapacity = UnitConversions.convert(clg_coil.ratedTotalCoolingCapacity.get, 'W', 'Btu/hr')
2308
+ # Number of speeds
2309
+ if hpxml_hvac.is_a?(HPXML::CoolingSystem) || hpxml_hvac.is_a?(HPXML::HeatPump)
2310
+ # Cooling
2311
+ if hpxml_hvac_ap.respond_to? :num_speeds
2312
+ num_speeds = hpxml_hvac_ap.num_speeds
2064
2313
  end
2065
-
2066
- elsif clg_coil.is_a? OpenStudio::Model::CoilCoolingDXMultiSpeed
2067
- hvac.NumSpeedsCooling = clg_coil.stages.size
2314
+ num_speeds = 1 if num_speeds.nil?
2315
+ hvac.NumSpeedsCooling = num_speeds
2068
2316
  if hvac.NumSpeedsCooling == 2
2069
2317
  hvac.OverSizeLimit = 1.2
2070
- else
2318
+ elsif hvac.NumSpeedsCooling > 2
2071
2319
  hvac.OverSizeLimit = 1.3
2072
2320
  end
2073
-
2074
- capacityRatioCooling = get_feature(equip, Constants.SizingInfoHVACCapacityRatioCooling, 'string')
2075
-
2076
- hvac.CapacityRatioCooling = capacityRatioCooling.split(',').map(&:to_f)
2077
-
2078
- if not equip.designSpecificationMultispeedObject.is_initialized
2079
- fail "DesignSpecificationMultispeedObject not set for #{equip.name}."
2321
+ end
2322
+ if hpxml_hvac.is_a?(HPXML::HeatingSystem) || hpxml_hvac.is_a?(HPXML::HeatPump)
2323
+ # Heating
2324
+ if hpxml_hvac_ap.respond_to? :num_speeds
2325
+ num_speeds = hpxml_hvac_ap.num_speeds
2080
2326
  end
2327
+ num_speeds = 1 if num_speeds.nil?
2328
+ hvac.NumSpeedsHeating = num_speeds
2329
+ end
2081
2330
 
2082
- perf = equip.designSpecificationMultispeedObject.get
2083
- hvac.FanspeedRatioCooling = []
2084
- perf.supplyAirflowRatioFields.each do |airflowRatioField|
2085
- if not airflowRatioField.coolingRatio.is_initialized
2086
- fail "Cooling airflow ratio not set for #{perf.name}"
2087
- end
2088
-
2089
- hvac.FanspeedRatioCooling << airflowRatioField.coolingRatio.get
2331
+ # HVAC installation quality
2332
+ if hpxml_hvac.respond_to? :charge_defect_ratio
2333
+ if [HPXML::HVACTypeCentralAirConditioner,
2334
+ HPXML::HVACTypeMiniSplitAirConditioner,
2335
+ HPXML::HVACTypeHeatPumpAirToAir,
2336
+ HPXML::HVACTypeHeatPumpMiniSplit,
2337
+ HPXML::HVACTypeHeatPumpGroundToAir].include? hvac.CoolType
2338
+ hvac.ChargeDefectRatio = hpxml_hvac.charge_defect_ratio
2090
2339
  end
2091
-
2092
- curves = []
2093
- hvac.SHRRated = []
2094
- clg_coil.stages.each_with_index do |stage, speed|
2095
- curves << stage.totalCoolingCapacityFunctionofTemperatureCurve
2096
- if not stage.grossRatedSensibleHeatRatio.is_initialized
2097
- fail "SHR not set for #{clg_coil.name}."
2340
+ end
2341
+ if hpxml_hvac.respond_to? :airflow_defect_ratio
2342
+ # Cooling
2343
+ if [HPXML::HVACTypeCentralAirConditioner,
2344
+ HPXML::HVACTypeMiniSplitAirConditioner,
2345
+ HPXML::HVACTypeHeatPumpAirToAir,
2346
+ HPXML::HVACTypeHeatPumpMiniSplit,
2347
+ HPXML::HVACTypeHeatPumpGroundToAir].include? hvac.CoolType
2348
+ if not hpxml_hvac.distribution_system.nil? # Exclude ductless
2349
+ hvac.AirflowDefectRatioCooling = hpxml_hvac.airflow_defect_ratio
2098
2350
  end
2099
-
2100
- hvac.SHRRated << stage.grossRatedSensibleHeatRatio.get
2101
- next if !stage.grossRatedTotalCoolingCapacity.is_initialized
2102
-
2103
- hvac.FixedCoolingCapacity = UnitConversions.convert(stage.grossRatedTotalCoolingCapacity.get, 'W', 'Btu/hr')
2104
- end
2105
- hvac.COOL_CAP_FT_SPEC = get_2d_vector_from_CAP_FT_SPEC_curves(curves, hvac.NumSpeedsCooling)
2106
-
2107
- if hvac.CoolType == Constants.ObjectNameMiniSplitHeatPump
2108
- ratedCFMperTonCooling = get_feature(equip, Constants.SizingInfoHVACRatedCFMperTonCooling, 'string')
2109
- hvac.RatedCFMperTonCooling = ratedCFMperTonCooling.split(',').map(&:to_f)
2110
2351
  end
2111
-
2112
- elsif clg_coil.is_a? OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit
2113
- hvac.NumSpeedsCooling = 1
2114
-
2115
- cOOL_CAP_FT_SPEC = [clg_coil.totalCoolingCapacityCoefficient1,
2116
- clg_coil.totalCoolingCapacityCoefficient2,
2117
- clg_coil.totalCoolingCapacityCoefficient3,
2118
- clg_coil.totalCoolingCapacityCoefficient4,
2119
- clg_coil.totalCoolingCapacityCoefficient5]
2120
- hvac.COOL_CAP_FT_SPEC = [HVAC.convert_curve_gshp(cOOL_CAP_FT_SPEC, true)]
2121
-
2122
- cOOL_SH_FT_SPEC = [clg_coil.sensibleCoolingCapacityCoefficient1,
2123
- clg_coil.sensibleCoolingCapacityCoefficient3,
2124
- clg_coil.sensibleCoolingCapacityCoefficient4,
2125
- clg_coil.sensibleCoolingCapacityCoefficient5,
2126
- clg_coil.sensibleCoolingCapacityCoefficient6]
2127
- hvac.COOL_SH_FT_SPEC = [HVAC.convert_curve_gshp(cOOL_SH_FT_SPEC, true)]
2128
-
2129
- cOIL_BF_FT_SPEC = get_feature(equip, Constants.SizingInfoGSHPCoil_BF_FT_SPEC, 'string')
2130
- hvac.COIL_BF_FT_SPEC = [cOIL_BF_FT_SPEC.split(',').map(&:to_f)]
2131
-
2132
- shr_rated = get_feature(equip, Constants.SizingInfoHVACSHR, 'string')
2133
- hvac.SHRRated = shr_rated.split(',').map(&:to_f)
2134
-
2135
- hvac.CoilBF = get_feature(equip, Constants.SizingInfoGSHPCoilBF, 'double')
2136
-
2137
- if clg_coil.ratedTotalCoolingCapacity.is_initialized
2138
- hvac.FixedCoolingCapacity = UnitConversions.convert(clg_coil.ratedTotalCoolingCapacity.get, 'W', 'Btu/hr')
2352
+ # Heating
2353
+ if [HPXML::HVACTypeFurnace,
2354
+ HPXML::HVACTypeHeatPumpAirToAir,
2355
+ HPXML::HVACTypeHeatPumpMiniSplit,
2356
+ HPXML::HVACTypeHeatPumpGroundToAir].include? hvac.HeatType
2357
+ if not hpxml_hvac.distribution_system.nil? # Exclude ductless
2358
+ hvac.AirflowDefectRatioHeating = hpxml_hvac.airflow_defect_ratio
2359
+ end
2139
2360
  end
2140
-
2141
- hvac.CoolingEIR = 1.0 / clg_coil.ratedCoolingCoefficientofPerformance
2142
-
2143
- hvac.GSHP_BoreSpacing = get_feature(equip, Constants.SizingInfoGSHPBoreSpacing, 'double')
2144
- hvac.GSHP_BoreHoles = get_feature(equip, Constants.SizingInfoGSHPBoreHoles, 'string')
2145
- hvac.GSHP_BoreHoles = nil if hvac.GSHP_BoreHoles.empty?
2146
- hvac.GSHP_BoreDepth = get_feature(equip, Constants.SizingInfoGSHPBoreDepth, 'string')
2147
- hvac.GSHP_BoreDepth = nil if hvac.GSHP_BoreDepth.empty?
2148
- hvac.GSHP_BoreConfig = get_feature(equip, Constants.SizingInfoGSHPBoreConfig, 'string')
2149
- hvac.GSHP_BoreConfig = nil if hvac.GSHP_BoreConfig.empty?
2150
- hvac.GSHP_SpacingType = get_feature(equip, Constants.SizingInfoGSHPUTubeSpacingType, 'string')
2151
- elsif not clg_coil.nil?
2152
- fail "Unexpected cooling coil: #{clg_coil.name}."
2153
2361
  end
2154
2362
 
2155
- if not htg_coil.nil?
2156
- ratedCFMperTonHeating = get_feature(equip, Constants.SizingInfoHVACRatedCFMperTonHeating, 'string', false)
2157
- if not ratedCFMperTonHeating.nil?
2158
- hvac.RatedCFMperTonHeating = ratedCFMperTonHeating.split(',').map(&:to_f)
2159
- end
2363
+ # Rated airflow rates
2364
+ if hpxml_hvac_ap.respond_to? :cool_rated_cfm_per_ton
2365
+ hvac.RatedCFMperTonCooling = hpxml_hvac_ap.cool_rated_cfm_per_ton
2160
2366
  end
2161
-
2162
- heatingLoadFraction = get_feature(equip, Constants.SizingInfoHVACFracHeatLoadServed, 'double', false)
2163
- if not heatingLoadFraction.nil?
2164
- hvac.HeatingLoadFraction = heatingLoadFraction
2367
+ if hpxml_hvac_ap.respond_to? :heat_rated_cfm_per_ton
2368
+ hvac.RatedCFMperTonHeating = hpxml_hvac_ap.heat_rated_cfm_per_ton
2165
2369
  end
2166
2370
 
2167
- if equip.is_a? OpenStudio::Model::ZoneHVACBaseboardConvectiveElectric
2168
- if equip.nominalCapacity.is_initialized
2169
- hvac.FixedHeatingCapacity = UnitConversions.convert(equip.nominalCapacity.get, 'W', 'Btu/hr')
2170
- end
2171
-
2172
- elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingElectric
2173
- hvac.NumSpeedsHeating = 1
2174
- if htg_coil.nominalCapacity.is_initialized
2175
- hvac.FixedHeatingCapacity = UnitConversions.convert(htg_coil.nominalCapacity.get, 'W', 'Btu/hr')
2176
- end
2177
-
2178
- elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingGas
2179
- hvac.NumSpeedsHeating = 1
2180
- if htg_coil.nominalCapacity.is_initialized
2181
- hvac.FixedHeatingCapacity = UnitConversions.convert(htg_coil.nominalCapacity.get, 'W', 'Btu/hr')
2182
- end
2183
-
2184
- elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingWaterBaseboard
2185
- hvac.NumSpeedsHeating = 1
2186
- if htg_coil.heatingDesignCapacity.is_initialized
2187
- hvac.FixedHeatingCapacity = UnitConversions.convert(htg_coil.heatingDesignCapacity.get, 'W', 'Btu/hr')
2188
- end
2189
-
2190
- hvac.BoilerDesignTemp = UnitConversions.convert(htg_coil.plantLoop.get.sizingPlant.designLoopExitTemperature, 'C', 'F')
2191
-
2192
- elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingWater
2193
- hvac.NumSpeedsHeating = 1
2194
- if htg_coil.ratedCapacity.is_initialized
2195
- hvac.FixedHeatingCapacity = UnitConversions.convert(htg_coil.ratedCapacity.get, 'W', 'Btu/hr')
2196
- end
2197
-
2198
- hvac.BoilerDesignTemp = UnitConversions.convert(htg_coil.plantLoop.get.sizingPlant.designLoopExitTemperature, 'C', 'F')
2199
-
2200
- elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingDXSingleSpeed
2201
- hvac.NumSpeedsHeating = 1
2202
-
2203
- curves = [htg_coil.totalHeatingCapacityFunctionofTemperatureCurve]
2204
- hvac.HEAT_CAP_FT_SPEC = get_2d_vector_from_CAP_FT_SPEC_curves(curves, hvac.NumSpeedsHeating)
2205
-
2206
- if htg_coil.ratedTotalHeatingCapacity.is_initialized
2207
- hvac.FixedHeatingCapacity = UnitConversions.convert(htg_coil.ratedTotalHeatingCapacity.get, 'W', 'Btu/hr')
2208
- end
2209
-
2210
- elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingDXMultiSpeed
2211
- hvac.NumSpeedsHeating = htg_coil.stages.size
2212
-
2213
- capacityRatioHeating = get_feature(equip, Constants.SizingInfoHVACCapacityRatioHeating, 'string')
2214
- hvac.CapacityRatioHeating = capacityRatioHeating.split(',').map(&:to_f)
2215
-
2216
- curves = []
2217
- htg_coil.stages.each_with_index do |stage, speed|
2218
- curves << stage.heatingCapacityFunctionofTemperatureCurve
2219
- next if !stage.grossRatedHeatingCapacity.is_initialized
2220
-
2221
- hvac.FixedHeatingCapacity = UnitConversions.convert(stage.grossRatedHeatingCapacity.get, 'W', 'Btu/hr')
2222
- end
2223
- hvac.HEAT_CAP_FT_SPEC = get_2d_vector_from_CAP_FT_SPEC_curves(curves, hvac.NumSpeedsHeating)
2371
+ # Capacity ratios
2372
+ if hpxml_hvac_ap.respond_to? :cool_capacity_ratios
2373
+ hvac.CapacityRatioCooling = hpxml_hvac_ap.cool_capacity_ratios
2374
+ end
2375
+ if hpxml_hvac_ap.respond_to? :heat_capacity_ratios
2376
+ hvac.CapacityRatioHeating = hpxml_hvac_ap.heat_capacity_ratios
2377
+ end
2224
2378
 
2225
- if hvac.HeatType == Constants.ObjectNameMiniSplitHeatPump
2226
- ratedCFMperTonHeating = get_feature(equip, Constants.SizingInfoHVACRatedCFMperTonHeating, 'string')
2227
- hvac.RatedCFMperTonHeating = ratedCFMperTonHeating.split(',').map(&:to_f)
2379
+ # Sizing speed
2380
+ hvac.SizingSpeed = get_sizing_speed(hvac.NumSpeedsCooling, hvac.CapacityRatioCooling)
2228
2381
 
2229
- hvac.HeatingCapacityOffset = get_feature(equip, Constants.SizingInfoHVACHeatingCapacityOffset, 'double')
2230
- end
2382
+ # Rated SHRs
2383
+ if hpxml_hvac_ap.respond_to? :cool_rated_shrs_gross
2384
+ hvac.SHRRated = hpxml_hvac_ap.cool_rated_shrs_gross
2385
+ end
2231
2386
 
2232
- elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit
2233
- hvac.NumSpeedsHeating = 1
2387
+ # Performance curves
2388
+ if hpxml_hvac_ap.respond_to? :cool_cap_ft_spec
2389
+ hvac.COOL_CAP_FT_SPEC = hpxml_hvac_ap.cool_cap_ft_spec
2390
+ end
2391
+ if hpxml_hvac_ap.respond_to? :cool_sh_ft_spec
2392
+ hvac.COOL_SH_FT_SPEC = hpxml_hvac_ap.cool_sh_ft_spec
2393
+ end
2394
+ if hpxml_hvac_ap.respond_to? :heat_cap_ft_spec
2395
+ hvac.HEAT_CAP_FT_SPEC = hpxml_hvac_ap.heat_cap_ft_spec
2396
+ end
2397
+ if hpxml_hvac_ap.respond_to? :cool_cap_fflow_spec
2398
+ hvac.COOL_CAP_FFLOW_SPEC = hpxml_hvac_ap.cool_cap_fflow_spec
2399
+ end
2400
+ if hpxml_hvac_ap.respond_to? :heat_cap_fflow_spec
2401
+ hvac.HEAT_CAP_FFLOW_SPEC = hpxml_hvac_ap.heat_cap_fflow_spec
2402
+ end
2234
2403
 
2235
- if htg_coil.ratedHeatingCapacity.is_initialized
2236
- hvac.FixedHeatingCapacity = UnitConversions.convert(htg_coil.ratedHeatingCapacity.get, 'W', 'Btu/hr')
2237
- end
2404
+ # WLHP
2405
+ if hpxml_hvac.respond_to? :heating_efficiency_cop
2406
+ hvac.HeatingCOP = hpxml_hvac.heating_efficiency_cop
2407
+ end
2238
2408
 
2239
- hvac.HeatingEIR = 1.0 / htg_coil.ratedHeatingCoefficientofPerformance
2409
+ # GSHP
2410
+ if hpxml_hvac_ap.respond_to? :u_tube_spacing_type
2411
+ hvac.GSHP_SpacingType = hpxml_hvac_ap.u_tube_spacing_type
2412
+ end
2413
+ if hpxml_hvac_ap.respond_to? :cool_rated_eirs
2414
+ hvac.CoolingEIR = hpxml_hvac_ap.cool_rated_eirs[0]
2415
+ end
2416
+ if hpxml_hvac_ap.respond_to? :heat_rated_eirs
2417
+ hvac.HeatingEIR = hpxml_hvac_ap.heat_rated_eirs[0]
2418
+ end
2419
+ if hvac.HeatType == HPXML::HVACTypeHeatPumpGroundToAir
2420
+ hvac.GSHP_design_chw = hpxml_hvac_ap.design_chw
2421
+ hvac.GSHP_design_delta_t = hpxml_hvac_ap.design_delta_t
2422
+ hvac.GSHP_design_hw = hpxml_hvac_ap.design_hw
2423
+ hvac.GSHP_bore_d = hpxml_hvac_ap.bore_diameter
2424
+ hvac.GSHP_pipe_od = hpxml_hvac_ap.pipe_od
2425
+ hvac.GSHP_pipe_id = hpxml_hvac_ap.pipe_id
2426
+ hvac.GSHP_pipe_cond = hpxml_hvac_ap.pipe_cond
2427
+ hvac.GSHP_ground_k = hpxml_hvac_ap.ground_conductivity
2428
+ hvac.GSHP_grout_k = hpxml_hvac_ap.grout_conductivity
2429
+ end
2240
2430
 
2241
- plant_loop = htg_coil.plantLoop.get
2242
- plant_loop.supplyComponents.each do |plc|
2243
- next if !plc.to_GroundHeatExchangerVertical.is_initialized
2431
+ # Evaporative cooler
2432
+ if hpxml_hvac_ap.respond_to? :effectiveness
2433
+ hvac.EvapCoolerEffectiveness = hpxml_hvac_ap.effectiveness
2434
+ end
2244
2435
 
2245
- hvac.GSHP_HXVertical = plc.to_GroundHeatExchangerVertical.get
2246
- end
2247
- if hvac.GSHP_HXVertical.nil?
2248
- fail 'Could not find GroundHeatExchangerVertical object on GSHP plant loop.'
2249
- end
2436
+ # Ducts
2437
+ # FUTURE: Consolidate w/ ducts code in measure.rb
2438
+ hvac.Ducts = []
2439
+ next unless not hpxml_hvac.distribution_system.nil?
2440
+ lto = { supply_percent: nil, supply_cfm25: nil, return_percent: nil, return_cfm25: nil }
2441
+ hpxml_hvac.distribution_system.duct_leakage_measurements.each do |m|
2442
+ next unless m.duct_leakage_total_or_to_outside == 'to outside'
2250
2443
 
2251
- hvac.GSHP_HXDTDesign = UnitConversions.convert(plant_loop.sizingPlant.loopDesignTemperatureDifference, 'K', 'R')
2252
- hvac.GSHP_HXCHWDesign = UnitConversions.convert(plant_loop.sizingPlant.designLoopExitTemperature, 'C', 'F')
2253
- hvac.GSHP_HXHWDesign = UnitConversions.convert(plant_loop.minimumLoopTemperature, 'C', 'F')
2254
- if hvac.GSHP_HXDTDesign.nil? || hvac.GSHP_HXCHWDesign.nil? || hvac.GSHP_HXHWDesign.nil?
2255
- fail 'Could not find GSHP plant loop.'
2444
+ if m.duct_leakage_units == HPXML::UnitsPercent && m.duct_type == HPXML::DuctTypeSupply
2445
+ lto[:supply_percent] = m.duct_leakage_value
2446
+ elsif m.duct_leakage_units == HPXML::UnitsCFM25 && m.duct_type == HPXML::DuctTypeSupply
2447
+ lto[:supply_cfm25] = m.duct_leakage_value
2448
+ elsif m.duct_leakage_units == HPXML::UnitsPercent && m.duct_type == HPXML::DuctTypeReturn
2449
+ lto[:return_percent] = m.duct_leakage_value
2450
+ elsif m.duct_leakage_units == HPXML::UnitsCFM25 && m.duct_type == HPXML::DuctTypeReturn
2451
+ lto[:return_cfm25] = m.duct_leakage_value
2256
2452
  end
2453
+ end
2454
+ total_uncond_supply_area = hpxml_hvac.distribution_system.total_unconditioned_duct_areas[HPXML::DuctTypeSupply]
2455
+ total_uncond_return_area = hpxml_hvac.distribution_system.total_unconditioned_duct_areas[HPXML::DuctTypeReturn]
2456
+ hpxml_hvac.distribution_system.ducts.each do |duct|
2457
+ next if [HPXML::LocationLivingSpace, HPXML::LocationBasementConditioned].include? duct.duct_location
2257
2458
 
2258
- hvac.GSHP_PumpWattsPerTon = get_feature(equip, Constants.SizingInfoHVACPumpPower, 'double')
2459
+ d = DuctInfo.new
2460
+ d.Side = duct.duct_type
2461
+ d.Location = duct.duct_location
2462
+ d.Area = duct.duct_surface_area
2259
2463
 
2260
- elsif not htg_coil.nil?
2261
- fail "Unexpected heating coil: #{htg_coil.name}."
2262
- end
2464
+ # Calculate R-value w/ air film
2465
+ d.Rvalue = Airflow.get_duct_insulation_rvalue(duct.duct_insulation_r_value, d.Side)
2263
2466
 
2264
- # Supplemental heating
2265
- if supp_htg_coil.is_a?(OpenStudio::Model::CoilHeatingElectric) || supp_htg_coil.is_a?(OpenStudio::Model::CoilHeatingGas)
2266
- if supp_htg_coil.nominalCapacity.is_initialized
2267
- hvac.FixedSuppHeatingCapacity = UnitConversions.convert(supp_htg_coil.nominalCapacity.get, 'W', 'Btu/hr')
2467
+ # Leakage to Outside apportioned to this duct
2468
+ if d.Side == HPXML::DuctTypeSupply
2469
+ d.LeakageFrac = lto[:supply_percent].to_f * d.Area / total_uncond_supply_area
2470
+ d.LeakageCFM25 = lto[:supply_cfm25].to_f * d.Area / total_uncond_supply_area
2471
+ elsif d.Side == HPXML::DuctTypeReturn
2472
+ d.LeakageFrac = lto[:return_percent].to_f * d.Area / total_uncond_return_area
2473
+ d.LeakageCFM25 = lto[:return_cfm25].to_f * d.Area / total_uncond_return_area
2268
2474
  end
2269
-
2270
- elsif not supp_htg_coil.nil?
2271
- fail "Unexpected supplemental heating coil: #{supp_htg_coil.name}."
2475
+ hvac.Ducts << d
2272
2476
  end
2477
+ # If all ducts are in conditioned space, treat leakage as going to outside
2478
+ if (lto[:supply_percent].to_f + lto[:supply_cfm25].to_f) > 0 && total_uncond_supply_area == 0
2479
+ d = DuctInfo.new
2480
+ d.Side = HPXML::DuctTypeSupply
2481
+ d.Location = HPXML::LocationOutside
2482
+ d.Area = 0.0
2483
+ d.Rvalue = Airflow.get_duct_insulation_rvalue(0.0, d.Side)
2484
+ d.LeakageFrac = lto[:supply_percent]
2485
+ d.LeakageCFM25 = lto[:supply_cfm25]
2486
+ hvac.Ducts << d
2487
+ end
2488
+ next unless (lto[:return_percent].to_f + lto[:return_cfm25].to_f) > 0 && total_uncond_return_area == 0
2489
+ d = DuctInfo.new
2490
+ d.Side = HPXML::DuctTypeReturn
2491
+ d.Location = HPXML::LocationOutside
2492
+ d.Area = 0.0
2493
+ d.Rvalue = Airflow.get_duct_insulation_rvalue(0.0, d.Side)
2494
+ d.LeakageFrac = lto[:return_percent]
2495
+ d.LeakageCFM25 = lto[:return_cfm25]
2496
+ hvac.Ducts << d
2273
2497
  end
2274
2498
 
2275
- return hvacs
2276
- end
2277
-
2278
- def self.get_2d_vector_from_CAP_FT_SPEC_curves(curves, num_speeds)
2279
- vector = []
2280
- curves.each do |curve|
2281
- bi = curve.to_CurveBiquadratic.get
2282
- c_si = [bi.coefficient1Constant, bi.coefficient2x, bi.coefficient3xPOW2, bi.coefficient4y, bi.coefficient5yPOW2, bi.coefficient6xTIMESY]
2283
- vector << HVAC.convert_curve_biquadratic(c_si, curves_in_ip = false)
2284
- end
2285
- if (num_speeds > 1) && (vector.size == 1)
2286
- # Repeat coefficients for each speed
2287
- for i in 1..num_speeds
2288
- vector << vector[0]
2289
- end
2290
- end
2291
- return vector
2499
+ return hvac
2292
2500
  end
2293
2501
 
2294
2502
  def self.process_curve_fit(airFlowRate, capacity, temp)
@@ -2296,16 +2504,23 @@ class HVACSizing
2296
2504
  return 0 if capacity == 0
2297
2505
 
2298
2506
  capacity_tons = UnitConversions.convert(capacity, 'Btu/hr', 'ton')
2299
- return MathTools.biquadratic(airFlowRate / capacity_tons, temp, @shr_biquadratic)
2507
+ return MathTools.biquadratic(airFlowRate / capacity_tons, temp, get_shr_biquadratic)
2508
+ end
2509
+
2510
+ def self.get_shr_biquadratic
2511
+ # Based on EnergyPlus's model for calculating SHR at off-rated conditions. This curve fit
2512
+ # avoids the iterations in the actual model. It does not account for altitude or variations
2513
+ # in the SHRRated. It is a function of ODB (MJ design temp) and CFM/Ton (from MJ)
2514
+ return [1.08464364, 0.002096954, 0, -0.005766327, 0, -0.000011147]
2300
2515
  end
2301
2516
 
2302
- def self.get_sizing_speed(hvac)
2303
- if hvac.NumSpeedsCooling > 1
2304
- sizingSpeed = hvac.NumSpeedsCooling # Default
2517
+ def self.get_sizing_speed(num_speeds_cooling, capacity_ratios_cooling)
2518
+ if num_speeds_cooling > 1
2519
+ sizingSpeed = num_speeds_cooling # Default
2305
2520
  sizingSpeed_Test = 10 # Initialize
2306
- for speed in 0..(hvac.NumSpeedsCooling - 1)
2521
+ for speed in 0..(num_speeds_cooling - 1)
2307
2522
  # Select curves for sizing using the speed with the capacity ratio closest to 1
2308
- temp = (hvac.CapacityRatioCooling[speed] - 1).abs
2523
+ temp = (capacity_ratios_cooling[speed] - 1).abs
2309
2524
  if temp <= sizingSpeed_Test
2310
2525
  sizingSpeed = speed
2311
2526
  sizingSpeed_Test = temp
@@ -2353,8 +2568,44 @@ class HVACSizing
2353
2568
  end
2354
2569
 
2355
2570
  # Infiltration UA
2356
- infiltration_cfm = get_feature(@spaces[space_type].thermalZone.get, Constants.SizingInfoZoneInfiltrationCFM, 'double', false)
2357
- infiltration_cfm = 0.0 if infiltration_cfm.nil?
2571
+ infiltration_cfm = nil
2572
+ ach = nil
2573
+ if [HPXML::LocationCrawlspaceVented, HPXML::LocationAtticVented].include? space_type
2574
+ # Vented space
2575
+ if space_type == HPXML::LocationCrawlspaceVented
2576
+ vented_crawl = @hpxml.foundations.select { |f| f.foundation_type == HPXML::FoundationTypeCrawlspaceVented }[0]
2577
+ sla = vented_crawl.vented_crawlspace_sla
2578
+ else
2579
+ vented_attic = @hpxml.attics.select { |f| f.attic_type == HPXML::AtticTypeVented }[0]
2580
+ if not vented_attic.vented_attic_sla.nil?
2581
+ sla = vented_attic.vented_attic_sla
2582
+ else
2583
+ ach = vented_attic.vented_attic_ach
2584
+ end
2585
+ end
2586
+ ach = Airflow.get_infiltration_ACH_from_SLA(sla, 8.202, weather) if ach.nil?
2587
+ else # Unvented space
2588
+ ach = 0.1 # Assumption
2589
+ end
2590
+ # FUTURE: Reuse code from measure.rb set_zone_volumes()
2591
+ if [HPXML::LocationAtticVented, HPXML::LocationAtticUnvented].include? space_type
2592
+ floor_area = @hpxml.frame_floors.select { |f| [f.interior_adjacent_to, f.exterior_adjacent_to].include? space_type }.map { |s| s.area }.sum(0.0)
2593
+ roofs = @hpxml.roofs.select { |r| r.interior_adjacent_to == space_type }
2594
+ avg_pitch = roofs.map { |r| r.pitch }.sum(0.0) / roofs.size
2595
+ # Assume square hip roof for volume calculations; energy results are very insensitive to actual volume
2596
+ length = floor_area**0.5
2597
+ height = 0.5 * Math.sin(Math.atan(avg_pitch / 12.0)) * length
2598
+ volume = [floor_area * height / 3.0, 0.01].max
2599
+ else # foundation/garage space
2600
+ floor_area = @hpxml.slabs.select { |s| s.interior_adjacent_to == space_type }.map { |s| s.area }.sum(0.0)
2601
+ if space_type == HPXML::LocationGarage
2602
+ height = 8.0
2603
+ else
2604
+ height = @hpxml.foundation_walls.select { |w| w.interior_adjacent_to == space_type }.map { |w| w.height }.max
2605
+ end
2606
+ volume = floor_area * height
2607
+ end
2608
+ infiltration_cfm = ach / UnitConversions.convert(1.0, 'hr', 'min') * volume
2358
2609
  outside_air_density = UnitConversions.convert(weather.header.LocalPressure, 'atm', 'Btu/ft^3') / (Gas.Air.r * (weather.data.AnnualAvgDrybulb + 460.0))
2359
2610
  space_UAs['infil'] = infiltration_cfm * outside_air_density * Gas.Air.cp * UnitConversions.convert(1.0, 'hr', 'min')
2360
2611
 
@@ -2404,8 +2655,8 @@ class HVACSizing
2404
2655
  # when the roof is insulated
2405
2656
  min_temp_rise = 5.0
2406
2657
 
2407
- max_cooling_temp = @conditioned_cool_design_temp + max_temp_rise
2408
- min_cooling_temp = @conditioned_cool_design_temp + min_temp_rise
2658
+ max_cooling_temp = @cool_setpoint + max_temp_rise
2659
+ min_cooling_temp = @cool_setpoint + min_temp_rise
2409
2660
 
2410
2661
  ua_conditioned = 0.0
2411
2662
  ua_outside = 0.0
@@ -2447,42 +2698,85 @@ class HVACSizing
2447
2698
  wall_ufactor = 1.0 / wall.insulation_assembly_r_value
2448
2699
 
2449
2700
  # The following correlations were estimated by analyzing MJ8 construction tables.
2450
- if [HPXML::WallTypeWoodStud, HPXML::WallTypeSteelStud].include? wall_type
2451
- if wall.insulation_cavity_r_value < 2
2452
- wall_group = 1 # A
2453
- elsif wall.insulation_cavity_r_value <= 11
2454
- wall_group = 2 # B
2455
- elsif wall.insulation_cavity_r_value <= 13
2456
- wall_group = 3 # C
2457
- elsif wall.insulation_cavity_r_value <= 15
2458
- wall_group = 4 # D
2459
- elsif wall.insulation_cavity_r_value <= 19
2460
- wall_group = 5 # E
2461
- elsif wall.insulation_cavity_r_value <= 21
2462
- wall_group = 6 # F
2463
- else
2464
- wall_group = 7 # G
2465
- end
2466
- # Adjust the wall group for rigid foam insulation
2467
- if (wall.insulation_continuous_r_value > 1) && (wall.insulation_continuous_r_value <= 7)
2468
- if wall.insulation_cavity_r_value < 2
2469
- wall_group += 2
2701
+ if wall_type == HPXML::WallTypeWoodStud
2702
+ if wall.siding == HPXML::SidingTypeBrick
2703
+ if wall_ufactor <= 0.070
2704
+ wall_group = 11 # K
2705
+ elsif wall_ufactor <= 0.083
2706
+ wall_group = 10 # J
2707
+ elsif wall_ufactor <= 0.095
2708
+ wall_group = 9 # I
2709
+ elsif wall_ufactor <= 0.100
2710
+ wall_group = 8 # H
2711
+ elsif wall_ufactor <= 0.130
2712
+ wall_group = 7 # G
2713
+ elsif wall_ufactor <= 0.175
2714
+ wall_group = 6 # F
2470
2715
  else
2471
- wall_group += 4
2716
+ wall_group = 5 # E
2472
2717
  end
2473
- elsif wall.insulation_continuous_r_value > 7
2474
- if wall.insulation_cavity_r_value < 2
2475
- wall_group += 4
2718
+ else
2719
+ if wall_ufactor <= 0.048
2720
+ wall_group = 10 # J
2721
+ elsif wall_ufactor <= 0.051
2722
+ wall_group = 9 # I
2723
+ elsif wall_ufactor <= 0.059
2724
+ wall_group = 8 # H
2725
+ elsif wall_ufactor <= 0.063
2726
+ wall_group = 7 # G
2727
+ elsif wall_ufactor <= 0.067
2728
+ wall_group = 6 # F
2729
+ elsif wall_ufactor <= 0.075
2730
+ wall_group = 5 # E
2731
+ elsif wall_ufactor <= 0.086
2732
+ wall_group = 4 # D
2733
+ elsif wall_ufactor <= 0.110
2734
+ wall_group = 3 # C
2735
+ elsif wall_ufactor <= 0.170
2736
+ wall_group = 2 # B
2476
2737
  else
2477
- wall_group += 6
2738
+ wall_group = 1 # A
2478
2739
  end
2479
2740
  end
2480
- # Adjust the wall group for brick siding
2741
+
2742
+ elsif wall_type == HPXML::WallTypeSteelStud
2481
2743
  if wall.siding == HPXML::SidingTypeBrick
2482
- if wall.insulation_cavity_r_value < 2
2483
- wall_group += 4
2744
+ if wall_ufactor <= 0.090
2745
+ wall_group = 11 # K
2746
+ elsif wall_ufactor <= 0.105
2747
+ wall_group = 10 # J
2748
+ elsif wall_ufactor <= 0.118
2749
+ wall_group = 9 # I
2750
+ elsif wall_ufactor <= 0.125
2751
+ wall_group = 8 # H
2752
+ elsif wall_ufactor <= 0.145
2753
+ wall_group = 7 # G
2754
+ elsif wall_ufactor <= 0.200
2755
+ wall_group = 6 # F
2756
+ else
2757
+ wall_group = 5 # E
2758
+ end
2759
+ else
2760
+ if wall_ufactor <= 0.066
2761
+ wall_group = 10 # J
2762
+ elsif wall_ufactor <= 0.070
2763
+ wall_group = 9 # I
2764
+ elsif wall_ufactor <= 0.075
2765
+ wall_group = 8 # H
2766
+ elsif wall_ufactor <= 0.081
2767
+ wall_group = 7 # G
2768
+ elsif wall_ufactor <= 0.088
2769
+ wall_group = 6 # F
2770
+ elsif wall_ufactor <= 0.100
2771
+ wall_group = 5 # E
2772
+ elsif wall_ufactor <= 0.105
2773
+ wall_group = 4 # D
2774
+ elsif wall_ufactor <= 0.120
2775
+ wall_group = 3 # C
2776
+ elsif wall_ufactor <= 0.200
2777
+ wall_group = 2 # B
2484
2778
  else
2485
- wall_group += 6
2779
+ wall_group = 1 # A
2486
2780
  end
2487
2781
  end
2488
2782
 
@@ -2511,24 +2805,20 @@ class HVACSizing
2511
2805
  end
2512
2806
 
2513
2807
  elsif wall_type == HPXML::WallTypeCMU
2514
- # Manual J uses the same wall group for filled or hollow block
2515
- if wall.insulation_cavity_r_value < 2
2516
- wall_group = 5 # E
2517
- elsif wall.insulation_cavity_r_value <= 11
2518
- wall_group = 8 # H
2519
- elsif wall.insulation_cavity_r_value <= 13
2520
- wall_group = 9 # I
2521
- elsif wall.insulation_cavity_r_value <= 15
2522
- wall_group = 9 # I
2523
- elsif wall.insulation_cavity_r_value <= 19
2808
+ # Table 4A - Construction Number 13
2809
+ if wall_ufactor <= 0.0575
2524
2810
  wall_group = 10 # J
2525
- elsif wall.insulation_cavity_r_value <= 21
2526
- wall_group = 11 # K
2811
+ elsif wall_ufactor <= 0.067
2812
+ wall_group = 9 # I
2813
+ elsif wall_ufactor <= 0.080
2814
+ wall_group = 8 # H
2815
+ elsif wall_ufactor <= 0.108
2816
+ wall_group = 7 # G
2817
+ elsif wall_ufactor <= 0.148
2818
+ wall_group = 6 # F
2527
2819
  else
2528
- wall_group = 11 # K
2820
+ wall_group = 5 # E
2529
2821
  end
2530
- # This is an estimate based on Table 4A - Construction Number 13
2531
- wall_group += (wall.insulation_continuous_r_value / 3.0).floor # Group is increased by approximately 1 letter for each R3
2532
2822
 
2533
2823
  elsif [HPXML::WallTypeBrick, HPXML::WallTypeAdobe].include? wall_type
2534
2824
  # Two Courses Brick
@@ -2569,32 +2859,40 @@ class HVACSizing
2569
2859
  return wall_group
2570
2860
  end
2571
2861
 
2572
- def self.gshp_hx_pipe_rvalue(pipe_od, pipe_id, pipe_cond)
2862
+ def self.gshp_coil_bf
2863
+ return 0.0806
2864
+ end
2865
+
2866
+ def self.gshp_coil_bf_ft_spec
2867
+ return [1.21005458, -0.00664200, 0.00000000, 0.00348246, 0.00000000, 0.00000000]
2868
+ end
2869
+
2870
+ def self.gshp_hx_pipe_rvalue(hvac)
2573
2871
  # Thermal Resistance of Pipe
2574
- return Math.log(pipe_od / pipe_id) / 2.0 / Math::PI / pipe_cond
2872
+ return Math.log(hvac.GSHP_pipe_od / hvac.GSHP_pipe_id) / 2.0 / Math::PI / hvac.GSHP_pipe_cond
2575
2873
  end
2576
2874
 
2577
- def self.gshp_hxbore_ft_per_ton(weather, bore_spacing, ground_conductivity, spacing_type, grout_conductivity, bore_diameter, pipe_od, pipe_r_value, heating_eir, cooling_eir, chw_design, hw_design, design_delta_t)
2578
- if spacing_type == 'b'
2875
+ def self.gshp_hxbore_ft_per_ton(weather, hvac, bore_spacing, pipe_r_value)
2876
+ if hvac.GSHP_SpacingType == 'b'
2579
2877
  beta_0 = 17.4427
2580
2878
  beta_1 = -0.6052
2581
- elsif spacing_type == 'c'
2879
+ elsif hvac.GSHP_SpacingType == 'c'
2582
2880
  beta_0 = 21.9059
2583
2881
  beta_1 = -0.3796
2584
- elsif spacing_type == 'as'
2882
+ elsif hvac.GSHP_SpacingType == 'as'
2585
2883
  beta_0 = 20.1004
2586
2884
  beta_1 = -0.94467
2587
2885
  end
2588
2886
 
2589
- r_value_ground = Math.log(bore_spacing / bore_diameter * 12.0) / 2.0 / Math::PI / ground_conductivity
2590
- r_value_grout = 1.0 / grout_conductivity / beta_0 / ((bore_diameter / pipe_od)**beta_1)
2887
+ r_value_ground = Math.log(bore_spacing / hvac.GSHP_bore_d * 12.0) / 2.0 / Math::PI / hvac.GSHP_ground_k
2888
+ r_value_grout = 1.0 / hvac.GSHP_grout_k / beta_0 / ((hvac.GSHP_bore_d / hvac.GSHP_pipe_od)**beta_1)
2591
2889
  r_value_bore = r_value_grout + pipe_r_value / 2.0 # Note: Convection resistance is negligible when calculated against Glhepro (Jeffrey D. Spitler, 2000)
2592
2890
 
2593
2891
  rtf_DesignMon_Heat = [0.25, (71.0 - weather.data.MonthlyAvgDrybulbs[0]) / @htd].max
2594
2892
  rtf_DesignMon_Cool = [0.25, (weather.data.MonthlyAvgDrybulbs[6] - 76.0) / @ctd].max
2595
2893
 
2596
- nom_length_heat = (1.0 - heating_eir) * (r_value_bore + r_value_ground * rtf_DesignMon_Heat) / (weather.data.AnnualAvgDrybulb - (2.0 * hw_design - design_delta_t) / 2.0) * UnitConversions.convert(1.0, 'ton', 'Btu/hr')
2597
- nom_length_cool = (1.0 + cooling_eir) * (r_value_bore + r_value_ground * rtf_DesignMon_Cool) / ((2.0 * chw_design + design_delta_t) / 2.0 - weather.data.AnnualAvgDrybulb) * UnitConversions.convert(1.0, 'ton', 'Btu/hr')
2894
+ nom_length_heat = (1.0 - hvac.HeatingEIR) * (r_value_bore + r_value_ground * rtf_DesignMon_Heat) / (weather.data.AnnualAvgDrybulb - (2.0 * hvac.GSHP_design_hw - hvac.GSHP_design_delta_t) / 2.0) * UnitConversions.convert(1.0, 'ton', 'Btu/hr')
2895
+ nom_length_cool = (1.0 + hvac.CoolingEIR) * (r_value_bore + r_value_ground * rtf_DesignMon_Cool) / ((2.0 * hvac.GSHP_design_chw + hvac.GSHP_design_delta_t) / 2.0 - weather.data.AnnualAvgDrybulb) * UnitConversions.convert(1.0, 'ton', 'Btu/hr')
2598
2896
 
2599
2897
  return nom_length_heat, nom_length_cool
2600
2898
  end
@@ -2602,9 +2900,9 @@ class HVACSizing
2602
2900
  def self.gshp_gfnc_coeff(bore_config, num_bore_holes, spacing_to_depth_ratio)
2603
2901
  # Set GFNC coefficients
2604
2902
  gfnc_coeff = nil
2605
- if bore_config == Constants.BoreConfigSingle
2903
+ if bore_config == 'single'
2606
2904
  gfnc_coeff = 2.681, 3.024, 3.320, 3.666, 3.963, 4.306, 4.645, 4.899, 5.222, 5.405, 5.531, 5.704, 5.821, 6.082, 6.304, 6.366, 6.422, 6.477, 6.520, 6.558, 6.591, 6.619, 6.640, 6.665, 6.893, 6.694, 6.715
2607
- elsif bore_config == Constants.BoreConfigLine
2905
+ elsif bore_config == 'line'
2608
2906
  if num_bore_holes == 2
2609
2907
  if spacing_to_depth_ratio <= 0.02
2610
2908
  gfnc_coeff = 2.681, 3.043, 3.397, 3.9, 4.387, 5.005, 5.644, 6.137, 6.77, 7.131, 7.381, 7.722, 7.953, 8.462, 8.9, 9.022, 9.13, 9.238, 9.323, 9.396, 9.46, 9.515, 9.556, 9.604, 9.636, 9.652, 9.678
@@ -2714,7 +3012,7 @@ class HVACSizing
2714
3012
  gfnc_coeff = 2.679, 3.023, 3.318, 3.664, 3.961, 4.306, 4.65, 4.838, 5.275, 5.587, 5.837, 6.238, 6.552, 7.399, 8.347, 8.654, 8.956, 9.283, 9.549, 9.79, 10.014, 10.209, 10.36, 10.541, 10.669, 10.732, 10.837
2715
3013
  end
2716
3014
  end
2717
- elsif bore_config == Constants.BoreConfigLconfig
3015
+ elsif bore_config == 'l-config'
2718
3016
  if num_bore_holes == 3
2719
3017
  if spacing_to_depth_ratio <= 0.02
2720
3018
  gfnc_coeff = 2.682, 3.052, 3.435, 4.036, 4.668, 5.519, 6.435, 7.155, 8.091, 8.626, 8.997, 9.504, 9.847, 10.605, 11.256, 11.434, 11.596, 11.755, 11.88, 11.988, 12.083, 12.163, 12.224, 12.294, 12.342, 12.365, 12.405
@@ -2764,7 +3062,7 @@ class HVACSizing
2764
3062
  gfnc_coeff = 2.679, 3.023, 3.318, 3.664, 3.961, 4.306, 4.65, 4.838, 5.27, 5.579, 5.828, 6.225, 6.535, 7.384, 8.244, 8.515, 8.768, 9.026, 9.244, 9.428, 9.595, 9.737, 9.845, 9.97, 10.057, 10.099, 10.168
2765
3063
  end
2766
3064
  end
2767
- elsif bore_config == Constants.BoreConfigL2config
3065
+ elsif bore_config == 'l2-config'
2768
3066
  if num_bore_holes == 8
2769
3067
  if spacing_to_depth_ratio <= 0.02
2770
3068
  gfnc_coeff = 2.685, 3.078, 3.547, 4.438, 5.521, 7.194, 9.237, 10.973, 13.311, 14.677, 15.634, 16.942, 17.831, 19.791, 21.462, 21.917, 22.329, 22.734, 23.052, 23.328, 23.568, 23.772, 23.925, 24.102, 24.224, 24.283, 24.384
@@ -2790,7 +3088,7 @@ class HVACSizing
2790
3088
  gfnc_coeff = 2.679, 3.023, 3.318, 3.664, 3.961, 4.307, 4.653, 4.842, 5.331, 5.731, 6.083, 6.683, 7.178, 8.6, 10.054, 10.508, 10.929, 11.356, 11.711, 12.009, 12.275, 12.5, 12.671, 12.866, 13, 13.064, 13.17
2791
3089
  end
2792
3090
  end
2793
- elsif bore_config == Constants.BoreConfigUconfig
3091
+ elsif bore_config == 'u-config'
2794
3092
  if num_bore_holes == 5
2795
3093
  if spacing_to_depth_ratio <= 0.02
2796
3094
  gfnc_coeff = 2.683, 3.057, 3.46, 4.134, 4.902, 6.038, 7.383, 8.503, 9.995, 10.861, 11.467, 12.294, 12.857, 14.098, 15.16, 15.449, 15.712, 15.97, 16.173, 16.349, 16.503, 16.633, 16.731, 16.844, 16.922, 16.96, 17.024
@@ -2828,7 +3126,7 @@ class HVACSizing
2828
3126
  gfnc_coeff = 2.679, 3.023, 3.318, 3.664, 3.961, 4.306, 4.65, 4.838, 5.277, 5.6, 5.87, 6.322, 6.698, 7.823, 9.044, 9.438, 9.809, 10.188, 10.506, 10.774, 11.015, 11.219, 11.374, 11.552, 11.674, 11.733, 11.83
2829
3127
  end
2830
3128
  end
2831
- elsif bore_config == Constants.BoreConfigOpenRectangle
3129
+ elsif bore_config == 'open-rectangle'
2832
3130
  if num_bore_holes == 8
2833
3131
  if spacing_to_depth_ratio <= 0.02
2834
3132
  gfnc_coeff = 2.684, 3.066, 3.497, 4.275, 5.229, 6.767, 8.724, 10.417, 12.723, 14.079, 15.03, 16.332, 17.217, 19.17, 20.835, 21.288, 21.698, 22.101, 22.417, 22.692, 22.931, 23.133, 23.286, 23.462, 23.583, 23.642, 23.742
@@ -2854,7 +3152,7 @@ class HVACSizing
2854
3152
  gfnc_coeff = 2.679, 3.023, 3.318, 3.664, 3.961, 4.306, 4.651, 4.839, 5.292, 5.636, 5.928, 6.425, 6.841, 8.089, 9.44, 9.875, 10.284, 10.7, 11.05, 11.344, 11.608, 11.831, 12.001, 12.196, 12.329, 12.393, 12.499
2855
3153
  end
2856
3154
  end
2857
- elsif bore_config == Constants.BoreConfigRectangle
3155
+ elsif bore_config == 'rectangle'
2858
3156
  if num_bore_holes == 4
2859
3157
  if spacing_to_depth_ratio <= 0.02
2860
3158
  gfnc_coeff = 2.684, 3.066, 3.493, 4.223, 5.025, 6.131, 7.338, 8.291, 9.533, 10.244, 10.737, 11.409, 11.865, 12.869, 13.73, 13.965, 14.178, 14.388, 14.553, 14.696, 14.821, 14.927, 15.007, 15.099, 15.162, 15.193, 15.245
@@ -3043,388 +3341,24 @@ class HVACSizing
3043
3341
 
3044
3342
  return f_values.sum() / f_values.size
3045
3343
  end
3046
-
3047
- def self.get_feature(obj, feature, datatype, fail_on_error = true)
3048
- val = nil
3049
- if datatype == 'string'
3050
- val = obj.additionalProperties.getFeatureAsString(feature)
3051
- elsif datatype == 'double'
3052
- val = obj.additionalProperties.getFeatureAsDouble(feature)
3053
- elsif datatype == 'boolean'
3054
- val = obj.additionalProperties.getFeatureAsBoolean(feature)
3055
- end
3056
- if not val.is_initialized
3057
- if fail_on_error
3058
- fail "Could not find additionalProperties value for '#{feature}' with datatype #{datatype} on object #{obj.name}."
3059
- end
3060
-
3061
- return
3062
- end
3063
- return val.get
3064
- end
3065
-
3066
- def self.set_object_values(model, hvac, hvac_final_values)
3067
- # Updates object properties in the model
3068
-
3069
- hvac.Objects.each do |object|
3070
- if object.is_a? OpenStudio::Model::AirLoopHVACUnitarySystem
3071
-
3072
- # Fan Airflow
3073
- if object.coolingCoil.is_initialized && object.heatingCoil.is_initialized
3074
- fan_airflow = [hvac_final_values.Heat_Airflow, hvac_final_values.Cool_Airflow].max
3075
- elsif object.coolingCoil.is_initialized
3076
- fan_airflow = hvac_final_values.Cool_Airflow
3077
- elsif object.heatingCoil.is_initialized
3078
- fan_airflow = hvac_final_values.Heat_Airflow
3079
- end
3080
- end
3081
-
3082
- if object.is_a?(OpenStudio::Model::AirLoopHVACUnitarySystem) && object.airLoopHVAC.is_initialized
3083
-
3084
- ## Air Loop HVAC Unitary System ##
3085
-
3086
- # Unitary System
3087
- object.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
3088
- if object.coolingCoil.is_initialized
3089
- object.setSupplyAirFlowRateDuringCoolingOperation(UnitConversions.convert(hvac_final_values.Cool_Airflow, 'cfm', 'm^3/s'))
3090
- else
3091
- object.setSupplyAirFlowRateDuringCoolingOperation(0.0)
3092
- end
3093
- object.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
3094
- if object.heatingCoil.is_initialized
3095
- object.setSupplyAirFlowRateDuringHeatingOperation(UnitConversions.convert(hvac_final_values.Heat_Airflow, 'cfm', 'm^3/s'))
3096
- else
3097
- object.setSupplyAirFlowRateDuringHeatingOperation(0.0)
3098
- end
3099
-
3100
- # Fan
3101
- fanonoff = object.supplyFan.get.to_FanOnOff.get
3102
- fanonoff.setMaximumFlowRate(hvac.FanspeedRatioCooling.max * UnitConversions.convert(fan_airflow + 0.01, 'cfm', 'm^3/s'))
3103
-
3104
- # Air Loop
3105
- air_loop = object.airLoopHVAC.get
3106
- air_loop.setDesignSupplyAirFlowRate(hvac.FanspeedRatioCooling.max * UnitConversions.convert(fan_airflow, 'cfm', 'm^3/s'))
3107
-
3108
- @cond_zone.airLoopHVACTerminals.each do |aterm|
3109
- next if air_loop != aterm.airLoopHVAC.get
3110
- next unless aterm.to_AirTerminalSingleDuctUncontrolled.is_initialized
3111
-
3112
- # Air Terminal
3113
- aterm = aterm.to_AirTerminalSingleDuctUncontrolled.get
3114
- aterm.setMaximumAirFlowRate(UnitConversions.convert(fan_airflow, 'cfm', 'm^3/s'))
3115
- end
3116
-
3117
- # Coils
3118
- setCoilsObjectValues(model, hvac, object, hvac_final_values)
3119
-
3120
- if hvac.has_type(Constants.ObjectNameGroundSourceHeatPump)
3121
-
3122
- clg_coil, htg_coil, supp_htg_coil = HVAC.get_coils_from_hvac_equip(model, object)
3123
-
3124
- if not htg_coil.nil?
3125
- plant_loop = htg_coil.plantLoop.get
3126
- elsif not clg_coil.nil?
3127
- plant_loop = clg_coil.plantLoop.get
3128
- end
3129
-
3130
- # Plant Loop
3131
- plant_loop.setMaximumLoopFlowRate(UnitConversions.convert(hvac_final_values.GSHP_Loop_flow, 'gal/min', 'm^3/s'))
3132
-
3133
- # Ground Heat Exchanger Vertical
3134
- hvac.GSHP_HXVertical.setDesignFlowRate(UnitConversions.convert(hvac_final_values.GSHP_Loop_flow, 'gal/min', 'm^3/s'))
3135
- hvac.GSHP_HXVertical.setNumberofBoreHoles(hvac_final_values.GSHP_Bore_Holes.to_i)
3136
- hvac.GSHP_HXVertical.setBoreHoleLength(UnitConversions.convert(hvac_final_values.GSHP_Bore_Depth, 'ft', 'm'))
3137
- hvac.GSHP_HXVertical.removeAllGFunctions
3138
- for i in 0..(hvac_final_values.GSHP_G_Functions[0].size - 1)
3139
- hvac.GSHP_HXVertical.addGFunction(hvac_final_values.GSHP_G_Functions[0][i], hvac_final_values.GSHP_G_Functions[1][i])
3140
- end
3141
-
3142
- plant_loop.supplyComponents.each do |plc|
3143
- next unless plc.to_PumpVariableSpeed.is_initialized
3144
-
3145
- # Pump
3146
- pump_w = hvac.GSHP_PumpWattsPerTon * UnitConversions.convert(clg_coil.ratedTotalCoolingCapacity.get, 'W', 'ton')
3147
- pump = plc.to_PumpVariableSpeed.get
3148
- pump.setRatedPowerConsumption(pump_w)
3149
- pump.setRatedFlowRate(HVAC.calc_pump_rated_flow_rate(0.75, pump_w, pump.ratedPumpHead))
3150
- HVAC.set_pump_power_ems_program(model, pump_w, pump, object)
3151
- end
3152
- end
3153
-
3154
- elsif object.is_a? OpenStudio::Model::AirLoopHVACUnitarySystem
3155
-
3156
- ## Zone HVAC Unitary System ##
3157
-
3158
- thermal_zone = object.thermalZone.get
3159
-
3160
- # Unitary System
3161
- object.setSupplyAirFlowRateMethodDuringCoolingOperation('SupplyAirFlowRate')
3162
- if object.coolingCoil.is_initialized
3163
- object.setSupplyAirFlowRateDuringCoolingOperation(UnitConversions.convert(hvac_final_values.Cool_Airflow, 'cfm', 'm^3/s'))
3164
- else
3165
- object.setSupplyAirFlowRateDuringCoolingOperation(0.0)
3166
- end
3167
- object.setSupplyAirFlowRateMethodDuringHeatingOperation('SupplyAirFlowRate')
3168
- if object.heatingCoil.is_initialized
3169
- object.setSupplyAirFlowRateDuringHeatingOperation(UnitConversions.convert(hvac_final_values.Heat_Airflow, 'cfm', 'm^3/s'))
3170
- else
3171
- object.setSupplyAirFlowRateDuringHeatingOperation(0.0)
3172
- end
3173
-
3174
- # Fan
3175
- fanonoff = object.supplyFan.get.to_FanOnOff.get
3176
- fanonoff.setMaximumFlowRate(UnitConversions.convert(fan_airflow + 0.01, 'cfm', 'm^3/s'))
3177
- fan_watts_per_cfm = hvac.FanWatts / fan_airflow
3178
- HVAC.set_fan_power(fanonoff, fan_watts_per_cfm)
3179
-
3180
- # Coils
3181
- setCoilsObjectValues(model, hvac, object, hvac_final_values)
3182
-
3183
- elsif object.is_a? OpenStudio::Model::EvaporativeCoolerDirectResearchSpecial
3184
-
3185
- ## Evaporative Cooler ##
3186
-
3187
- # Air Loop
3188
- vfr = UnitConversions.convert(hvac_final_values.Cool_Airflow, 'cfm', 'm^3/s')
3189
- # evap cooler design flow rate
3190
- object.setPrimaryAirDesignFlowRate(vfr)
3191
- # air loop object design flow rates
3192
- air_loop = object.airLoopHVAC.get
3193
- air_loop.setDesignSupplyAirFlowRate(vfr)
3194
- fan = air_loop.supplyFan.get.to_FanVariableVolume.get
3195
- fan.setMaximumFlowRate(vfr)
3196
- oa_system = air_loop.components.select { |comp| comp.to_AirLoopHVACOutdoorAirSystem.is_initialized }[0].to_AirLoopHVACOutdoorAirSystem.get
3197
- oa_controller = oa_system.getControllerOutdoorAir
3198
- oa_controller.setMaximumOutdoorAirFlowRate(vfr)
3199
-
3200
- # Fan power
3201
- if fan.fanEfficiency == 1 # Not user specified, so default here
3202
- fan_watts_per_cfm = [2.79 * hvac_final_values.Cool_Airflow**-0.29, 0.6].min # fit of efficacy to air flow from the CEC listed equipment W/cfm
3203
- HVAC.set_fan_power(fan, fan_watts_per_cfm)
3204
- end
3205
-
3206
- @cond_zone.airLoopHVACTerminals.each do |aterm|
3207
- next if air_loop != aterm.airLoopHVAC.get
3208
- next unless aterm.to_AirTerminalSingleDuctVAVNoReheat.is_initialized
3209
-
3210
- # Air Terminal
3211
- aterm = aterm.to_AirTerminalSingleDuctVAVNoReheat.get
3212
- aterm.setMaximumAirFlowRate(vfr)
3213
- end
3214
-
3215
- elsif object.is_a?(OpenStudio::Model::ZoneHVACBaseboardConvectiveWater) || object.is_a?(OpenStudio::Model::ZoneHVACFourPipeFanCoil)
3216
-
3217
- ## Hot Water Boiler ##
3218
-
3219
- plant_loop = object.heatingCoil.plantLoop.get
3220
-
3221
- max_water_flow = UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'W') / UnitConversions.convert(20.0, 'R', 'K') / 4.186 / 998.2 / 1000.0 * 2.0
3222
- bb_UA = UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'W') / UnitConversions.convert(hvac.BoilerDesignTemp - 10.0 - 95.0, 'R', 'K') * 3.0
3223
- if object.is_a? OpenStudio::Model::ZoneHVACBaseboardConvectiveWater
3224
- # Baseboard Coil
3225
- coil = object.heatingCoil.to_CoilHeatingWaterBaseboard.get
3226
- coil.setUFactorTimesAreaValue(bb_UA)
3227
- coil.setMaximumWaterFlowRate(max_water_flow)
3228
- coil.setHeatingDesignCapacityMethod('HeatingDesignCapacity')
3229
- elsif object.is_a? OpenStudio::Model::ZoneHVACFourPipeFanCoil
3230
- coil = object.heatingCoil.to_CoilHeatingWater.get
3231
- coil.setRatedCapacity(UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'W'))
3232
- coil.setUFactorTimesAreaValue(bb_UA)
3233
- coil.setMaximumWaterFlowRate(max_water_flow)
3234
- coil.setPerformanceInputMethod('NominalCapacity')
3235
-
3236
- max_air_flow = UnitConversions.convert(400.0 * UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'ton'), 'cfm', 'm^3/s') # Assumes 400 cfm/ton
3237
- object.setMaximumSupplyAirFlowRate(max_air_flow)
3238
- object.setMaximumHotWaterFlowRate(max_water_flow)
3239
- object.supplyAirFan.to_FanOnOff.get.setMaximumFlowRate(max_air_flow)
3240
- end
3241
-
3242
- plant_loop.components.each do |component|
3243
- # Boiler
3244
- if component.to_BoilerHotWater.is_initialized
3245
- boiler = component.to_BoilerHotWater.get
3246
- boiler.setNominalCapacity(UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'W'))
3247
- end
3248
- end
3249
-
3250
- elsif object.is_a? OpenStudio::Model::ZoneHVACBaseboardConvectiveElectric
3251
-
3252
- ## Electric Baseboard ##
3253
-
3254
- thermal_zone = object.thermalZone.get
3255
-
3256
- # Baseboard
3257
- object.setNominalCapacity(UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'W'))
3258
-
3259
- elsif object.is_a? OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner
3260
-
3261
- ## Window AC ##
3262
-
3263
- thermal_zone = object.thermalZone.get
3264
-
3265
- # PTAC
3266
- object.setSupplyAirFlowRateDuringCoolingOperation(UnitConversions.convert(hvac_final_values.Cool_Airflow, 'cfm', 'm^3/s'))
3267
- object.setSupplyAirFlowRateDuringHeatingOperation(0.00001)
3268
- object.setSupplyAirFlowRateWhenNoCoolingorHeatingisNeeded(0.0)
3269
- object.setOutdoorAirFlowRateDuringCoolingOperation(0.0)
3270
- object.setOutdoorAirFlowRateDuringHeatingOperation(0.0)
3271
- object.setOutdoorAirFlowRateWhenNoCoolingorHeatingisNeeded(0.0)
3272
-
3273
- # Fan
3274
- fanonoff = object.supplyAirFan.to_FanOnOff.get
3275
- fanonoff.setMaximumFlowRate(UnitConversions.convert(hvac_final_values.Cool_Airflow, 'cfm', 'm^3/s'))
3276
-
3277
- # Coils
3278
- setCoilsObjectValues(model, hvac, object, hvac_final_values)
3279
-
3280
- # Heating Coil override
3281
- ptac_htg_coil = object.heatingCoil.to_CoilHeatingElectric.get
3282
- ptac_htg_coil.setNominalCapacity(0.0)
3283
-
3284
- else
3285
- fail "Unexpected object type: #{object.class}."
3286
-
3287
- end # object type
3288
- end # hvac Object
3289
- end
3290
-
3291
- def self.setCoilsObjectValues(model, hvac, equip, hvac_final_values)
3292
- clg_coil, htg_coil, supp_htg_coil = HVAC.get_coils_from_hvac_equip(model, equip)
3293
-
3294
- # Cooling coil
3295
- if clg_coil.is_a? OpenStudio::Model::CoilCoolingDXSingleSpeed
3296
- clg_coil.setRatedTotalCoolingCapacity(UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'W'))
3297
- clg_coil.setRatedAirFlowRate(UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'ton') * UnitConversions.convert(hvac.RatedCFMperTonCooling[0], 'cfm', 'm^3/s'))
3298
- elsif clg_coil.is_a? OpenStudio::Model::CoilCoolingDXMultiSpeed
3299
- clg_coil.stages.each_with_index do |stage, speed|
3300
- stage.setGrossRatedTotalCoolingCapacity(UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'W') * hvac.CapacityRatioCooling[speed])
3301
- if clg_coil.name.to_s.start_with?(Constants.ObjectNameAirSourceHeatPump) || clg_coil.name.to_s.start_with?(Constants.ObjectNameCentralAirConditioner)
3302
- stage.setRatedAirFlowRate(UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'ton') * UnitConversions.convert(hvac.RatedCFMperTonCooling[speed], 'cfm', 'm^3/s') * hvac.CapacityRatioCooling[speed])
3303
- elsif clg_coil.name.to_s.start_with? Constants.ObjectNameMiniSplitHeatPump
3304
- stage.setRatedAirFlowRate(UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'ton') * UnitConversions.convert(hvac.RatedCFMperTonCooling[speed], 'cfm', 'm^3/s'))
3305
- end
3306
- end
3307
-
3308
- elsif clg_coil.is_a? OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit
3309
- clg_coil.setRatedAirFlowRate(UnitConversions.convert(hvac_final_values.Cool_Airflow, 'cfm', 'm^3/s'))
3310
- clg_coil.setRatedWaterFlowRate(UnitConversions.convert(hvac_final_values.GSHP_Loop_flow, 'gal/min', 'm^3/s'))
3311
- clg_coil.setRatedTotalCoolingCapacity(UnitConversions.convert(hvac_final_values.Cool_Capacity, 'Btu/hr', 'W'))
3312
- clg_coil.setRatedSensibleCoolingCapacity(UnitConversions.convert(hvac_final_values.Cool_Capacity_Sens, 'Btu/hr', 'W'))
3313
-
3314
- end
3315
-
3316
- # Heating coil
3317
- if htg_coil.is_a? OpenStudio::Model::CoilHeatingElectric
3318
- if not equip.is_a? OpenStudio::Model::ZoneHVACPackagedTerminalAirConditioner
3319
- htg_coil.setNominalCapacity(UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'W'))
3320
- end
3321
-
3322
- elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingGas
3323
- htg_coil.setNominalCapacity(UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'W'))
3324
-
3325
- elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingDXSingleSpeed
3326
- htg_coil.setRatedTotalHeatingCapacity(UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'W'))
3327
- if htg_coil.name.to_s.start_with? Constants.ObjectNameWaterLoopHeatPump
3328
- htg_coil.setRatedAirFlowRate(UnitConversions.convert(hvac_final_values.Heat_Airflow, 'cfm', 'm^3/s'))
3329
- else
3330
- htg_coil.setRatedAirFlowRate(UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'ton') * UnitConversions.convert(hvac.RatedCFMperTonHeating[0], 'cfm', 'm^3/s'))
3331
- end
3332
-
3333
- elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingDXMultiSpeed
3334
- htg_coil.stages.each_with_index do |stage, speed|
3335
- stage.setGrossRatedHeatingCapacity(UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'W') * hvac.CapacityRatioHeating[speed])
3336
- if htg_coil.name.to_s.start_with? Constants.ObjectNameAirSourceHeatPump
3337
- stage.setRatedAirFlowRate(UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'ton') * UnitConversions.convert(hvac.RatedCFMperTonHeating[speed], 'cfm', 'm^3/s') * hvac.CapacityRatioHeating[speed])
3338
- elsif htg_coil.name.to_s.start_with? Constants.ObjectNameMiniSplitHeatPump
3339
- stage.setRatedAirFlowRate(UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'ton') * UnitConversions.convert(hvac.RatedCFMperTonHeating[speed], 'cfm', 'm^3/s'))
3340
- end
3341
- end
3342
-
3343
- elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit
3344
- htg_coil.setRatedAirFlowRate(UnitConversions.convert(hvac_final_values.Heat_Airflow, 'cfm', 'm^3/s'))
3345
- htg_coil.setRatedWaterFlowRate(UnitConversions.convert(hvac_final_values.GSHP_Loop_flow, 'gal/min', 'm^3/s'))
3346
- htg_coil.setRatedHeatingCapacity(UnitConversions.convert(hvac_final_values.Heat_Capacity, 'Btu/hr', 'W'))
3347
-
3348
- end
3349
-
3350
- # Supplemental heating coil
3351
- if supp_htg_coil.is_a?(OpenStudio::Model::CoilHeatingElectric) || supp_htg_coil.is_a?(OpenStudio::Model::CoilHeatingGas)
3352
- supp_htg_coil.setNominalCapacity(UnitConversions.convert(hvac_final_values.Heat_Capacity_Supp, 'Btu/hr', 'W'))
3353
- end
3354
- end
3355
-
3356
- def self.display_zone_loads(zone_loads)
3357
- s = "Zone Loads for #{@cond_zone.name}:"
3358
- properties = [
3359
- :Heat_Windows, :Heat_Skylights,
3360
- :Heat_Doors, :Heat_Walls,
3361
- :Heat_Roofs, :Heat_Floors,
3362
- :Heat_Infil,
3363
- :Cool_Windows, :Cool_Skylights,
3364
- :Cool_Doors, :Cool_Walls,
3365
- :Cool_Roofs, :Cool_Floors,
3366
- :Cool_Infil_Sens, :Cool_Infil_Lat,
3367
- :Cool_IntGains_Sens, :Cool_IntGains_Lat,
3368
- ]
3369
- properties.each do |property|
3370
- s += "\n#{property.to_s.gsub('_', ' ')} = #{zone_loads.send(property).round(0)} Btu/hr"
3371
- end
3372
- @runner.registerInfo("#{s}\n")
3373
- end
3374
-
3375
- def self.display_hvac_final_values_results(hvac_final_values, hvac)
3376
- s = "Final Results for #{hvac.Objects[0].name}:"
3377
- loads = [
3378
- :Heat_Load, :Heat_Load_Ducts,
3379
- :Cool_Load_Lat, :Cool_Load_Sens,
3380
- :Cool_Load_Ducts_Lat, :Cool_Load_Ducts_Sens,
3381
- ]
3382
- caps = [
3383
- :Cool_Capacity, :Cool_Capacity_Sens,
3384
- :Heat_Capacity, :Heat_Capacity_Supp,
3385
- ]
3386
- airflows = [
3387
- :Cool_Airflow, :Heat_Airflow,
3388
- ]
3389
- loads.each do |load|
3390
- s += "\n#{load.to_s.gsub('_', ' ')} = #{hvac_final_values.send(load).round(0)} Btu/hr"
3391
- end
3392
- caps.each do |cap|
3393
- s += "\n#{cap.to_s.gsub('_', ' ')} = #{hvac_final_values.send(cap).round(0)} Btu/hr"
3394
- end
3395
- airflows.each do |airflow|
3396
- s += "\n#{airflow.to_s.gsub('_', ' ')} = #{hvac_final_values.send(airflow).round(0)} cfm"
3397
- end
3398
- @runner.registerInfo("#{s}\n")
3399
- end
3400
3344
  end
3401
3345
 
3402
- class ZoneLoads
3403
- # Thermal zone loads
3346
+ class DesignLoads
3404
3347
  def initialize
3405
3348
  end
3406
- attr_accessor(:Cool_Windows, :Cool_Skylights, :Cool_Doors, :Cool_Walls, :Cool_Roofs, :Cool_Floors,
3407
- :Cool_Infil_Sens, :Cool_Infil_Lat, :Cool_IntGains_Sens, :Cool_IntGains_Lat,
3349
+ attr_accessor(:Cool_Sens, :Cool_Lat, :Cool_Tot, :Heat_Tot, :Heat_Ducts, :Cool_Ducts_Sens, :Cool_Ducts_Lat,
3350
+ :Cool_Windows, :Cool_Skylights, :Cool_Doors, :Cool_Walls, :Cool_Roofs, :Cool_Floors,
3351
+ :Cool_Ceilings, :Cool_Infil_Sens, :Cool_Infil_Lat, :Cool_IntGains_Sens, :Cool_IntGains_Lat,
3408
3352
  :Heat_Windows, :Heat_Skylights, :Heat_Doors, :Heat_Walls, :Heat_Roofs, :Heat_Floors,
3409
- :Heat_Infil)
3410
- end
3411
-
3412
- class InitialLoads
3413
- # Initial loads (aggregated across thermal zones and excluding ducts)
3414
- def initialize
3415
- end
3416
- attr_accessor(:Cool_Sens, :Cool_Lat, :Cool_Tot, :Heat)
3353
+ :Heat_Slabs, :Heat_Ceilings, :Heat_InfilVent)
3417
3354
  end
3418
3355
 
3419
- class FinalValues
3420
- # Final loads (including ducts), airflow rates, equipment capacities, etc.
3356
+ class HVACSizingValues
3421
3357
  def initialize
3422
3358
  end
3423
3359
  attr_accessor(:Cool_Load_Sens, :Cool_Load_Lat, :Cool_Load_Tot,
3424
- :Cool_Load_Ducts_Sens, :Cool_Load_Ducts_Lat, :Cool_Load_Ducts_Tot,
3425
3360
  :Cool_Capacity, :Cool_Capacity_Sens, :Cool_Airflow,
3426
- :Heat_Load, :Heat_Load_Ducts,
3427
- :Heat_Capacity, :Heat_Capacity_Supp, :Heat_Airflow,
3361
+ :Heat_Load, :Heat_Capacity, :Heat_Capacity_Supp, :Heat_Airflow,
3428
3362
  :GSHP_Loop_flow, :GSHP_Bore_Holes, :GSHP_Bore_Depth, :GSHP_G_Functions)
3429
3363
  end
3430
3364
 
@@ -3439,37 +3373,29 @@ class HVACInfo
3439
3373
  self.CapacityRatioHeating = [1.0]
3440
3374
  self.OverSizeLimit = 1.15
3441
3375
  self.OverSizeDelta = 15000.0
3442
- self.FanspeedRatioCooling = [1.0]
3443
3376
  self.Ducts = []
3377
+ self.AirflowDefectRatioCooling = 0.0
3378
+ self.AirflowDefectRatioHeating = 0.0
3444
3379
  end
3445
3380
 
3446
- def has_type(name_or_names)
3447
- if not name_or_names.is_a? Array
3448
- name_or_names = [name_or_names]
3449
- end
3450
- name_or_names.each do |name|
3451
- next unless (self.HeatType == name) || (self.CoolType == name)
3452
-
3453
- return true
3454
- end
3455
- return false
3456
- end
3457
-
3458
- attr_accessor(:HeatType, :CoolType, :Handle, :Objects, :Ducts, :NumSpeedsCooling, :NumSpeedsHeating,
3381
+ attr_accessor(:HeatType, :CoolType, :Ducts, :NumSpeedsCooling, :NumSpeedsHeating,
3459
3382
  :FixedCoolingCapacity, :FixedHeatingCapacity, :FixedSuppHeatingCapacity,
3460
- :RatedCFMperTonCooling, :RatedCFMperTonHeating,
3461
- :COOL_CAP_FT_SPEC, :HEAT_CAP_FT_SPEC, :COOL_SH_FT_SPEC, :COIL_BF_FT_SPEC,
3462
- :SHRRated, :CapacityRatioCooling, :CapacityRatioHeating, :FanWatts,
3463
- :HeatingCapacityOffset, :OverSizeLimit, :OverSizeDelta, :FanspeedRatioCooling,
3464
- :BoilerDesignTemp, :CoilBF, :HeatingEIR, :CoolingEIR, :SizingSpeed,
3465
- :GSHP_PumpWattsPerTon, :GSHP_HXVertical, :GSHP_HXDTDesign, :GSHP_HXCHWDesign, :GSHP_HXHWDesign,
3466
- :GSHP_BoreSpacing, :GSHP_BoreHoles, :GSHP_BoreDepth, :GSHP_BoreConfig, :GSHP_SpacingType,
3383
+ :AirflowDefectRatioCooling, :AirflowDefectRatioHeating,
3384
+ :RatedCFMperTonCooling, :RatedCFMperTonHeating, :ChargeDefectRatio,
3385
+ :COOL_CAP_FT_SPEC, :HEAT_CAP_FT_SPEC, :COOL_SH_FT_SPEC,
3386
+ :COOL_CAP_FFLOW_SPEC, :HEAT_CAP_FFLOW_SPEC,
3387
+ :SHRRated, :CapacityRatioCooling, :CapacityRatioHeating,
3388
+ :OverSizeLimit, :OverSizeDelta,
3389
+ :HeatingEIR, :CoolingEIR, :SizingSpeed, :HeatingCOP,
3390
+ :GSHP_SpacingType, :EvapCoolerEffectiveness,
3467
3391
  :HeatingLoadFraction, :CoolingLoadFraction, :SupplyAirTemp, :LeavingAirTemp,
3468
- :EvapCoolerEffectiveness)
3392
+ :GSHP_design_chw, :GSHP_design_delta_t, :GSHP_design_hw, :GSHP_bore_d,
3393
+ :GSHP_pipe_od, :GSHP_pipe_id, :GSHP_pipe_cond, :GSHP_ground_k, :GSHP_grout_k)
3469
3394
  end
3470
3395
 
3471
3396
  class DuctInfo
3472
3397
  # Model info for a duct
3398
+ # FUTURE: Remove class; use either airflow.rb Duct class or HPXML Ducts class directly
3473
3399
  def initial
3474
3400
  end
3475
3401
  attr_accessor(:LeakageFrac, :LeakageCFM25, :Area, :Rvalue, :Location, :Side)