Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ __New Features__
- Clarifies that Capacity=-1 can be used to autosize HVAC equipment for research purposes or to run tests.
- It should *not* be used for a real home; a warning will be issued when it's used.
- Allow alternative label energy use (W) input for ceiling fans.
- Allows detailed heating and cooling performance data (min/max COPs and capacities at different outdoor temperatures) for variable-speed systems.

__Bugfixes__
- Fixes incorrect Reference Home mechanical ventilation flowrate for attached units (when Aext is not 1).
Expand Down
222 changes: 144 additions & 78 deletions docs/source/workflow_inputs.rst

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions rulesets/resources/301ruleset.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1311,6 +1311,10 @@ def self.set_systems_hvac_rated(orig_bldg, new_bldg)
integrated_heating_system_efficiency_percent: orig_cooling_system.integrated_heating_system_efficiency_percent,
integrated_heating_system_fraction_heat_load_served: orig_cooling_system.integrated_heating_system_fraction_heat_load_served,
htg_seed_id: htg_seed_id)

orig_cooling_system.cooling_detailed_performance_data.each_with_index do |cdp, idx|
new_bldg.cooling_systems[-1].cooling_detailed_performance_data[idx] = cdp
end
end
# Add reference cooling system for residual load
if (sum_frac_cool_load < 0.99) # Accommodate systems that don't quite sum to 1 due to rounding
Expand Down Expand Up @@ -1367,6 +1371,14 @@ def self.set_systems_hvac_rated(orig_bldg, new_bldg)
charge_defect_ratio: charge_defect_ratio,
htg_seed_id: orig_heat_pump.htg_seed_id.nil? ? orig_heat_pump.id : orig_heat_pump.htg_seed_id,
clg_seed_id: orig_heat_pump.clg_seed_id.nil? ? orig_heat_pump.id : orig_heat_pump.clg_seed_id)

orig_heat_pump.heating_detailed_performance_data.each_with_index do |hdp, idx|
new_bldg.heat_pumps[-1].heating_detailed_performance_data[idx] = hdp
end

orig_heat_pump.cooling_detailed_performance_data.each_with_index do |cdp, idx|
new_bldg.heat_pumps[-1].cooling_detailed_performance_data[idx] = cdp
end
end
# Add reference heat pump for residual load
if (not has_fuel) && (sum_frac_heat_load < 0.99) # Accommodate systems that don't quite sum to 1 due to rounding
Expand Down
38 changes: 38 additions & 0 deletions rulesets/resources/301validator.xml
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@
<sch:assert role='ERROR' test='count(h:AnnualCoolingEfficiency[h:Units="SEER" or h:Units="SEER2"]/h:Value) = 1'>Expected 1 element(s) for xpath: AnnualCoolingEfficiency[Units="SEER" or Units="SEER2"]/Value</sch:assert>
<sch:assert role='ERROR' test='count(h:SensibleHeatFraction) &lt;= 1'>Expected 0 or 1 element(s) for xpath: SensibleHeatFraction</sch:assert>
<sch:assert role='ERROR' test='number(h:SensibleHeatFraction) &gt; 0.5 or not(h:SensibleHeatFraction)'>Expected SensibleHeatFraction to be greater than 0.5</sch:assert>
<sch:assert role='ERROR' test='count(h:CoolingDetailedPerformanceData) &lt;= 1'>Expected 0 or 1 element(s) for xpath: CoolingDetailedPerformanceData</sch:assert> <!-- See [CoolingDetailedPerformanceData]-->
<sch:assert role='ERROR' test='count(h:IntegratedHeatingSystemFuel) = 0'>Expected 0 element(s) for xpath: IntegratedHeatingSystemFuel</sch:assert>
<sch:assert role='ERROR' test='count(h:extension/h:FanPowerWattsPerCFM) = 1'>Expected 1 element(s) for xpath: extension/FanPowerWattsPerCFM</sch:assert>
<sch:assert role='ERROR' test='number(h:extension/h:FanPowerWattsPerCFM) &gt;= 0 or not(h:extension/h:FanPowerWattsPerCFM)'>Expected extension/FanPowerWattsPerCFM to be greater than or equal to 0</sch:assert>
Expand Down Expand Up @@ -753,6 +754,7 @@
<sch:assert role='ERROR' test='count(h:AnnualCoolingEfficiency[h:Units="SEER" or h:Units="SEER2"]/h:Value) = 1'>Expected 1 element(s) for xpath: AnnualCoolingEfficiency[Units="SEER" or Units="SEER2"]/Value</sch:assert>
<sch:assert role='ERROR' test='count(h:SensibleHeatFraction) &lt;= 1'>Expected 0 or 1 element(s) for xpath: SensibleHeatFraction</sch:assert>
<sch:assert role='ERROR' test='number(h:SensibleHeatFraction) &gt; 0.5 or not(h:SensibleHeatFraction)'>Expected SensibleHeatFraction to be greater than 0.5</sch:assert>
<sch:assert role='ERROR' test='count(h:CoolingDetailedPerformanceData) &lt;= 1'>Expected 0 or 1 element(s) for xpath: CoolingDetailedPerformanceData</sch:assert> <!-- See [CoolingDetailedPerformanceData]-->
<sch:assert role='ERROR' test='count(h:IntegratedHeatingSystemFuel) = 0'>Expected 0 element(s) for xpath: IntegratedHeatingSystemFuel</sch:assert>
<sch:assert role='ERROR' test='count(h:extension/h:FanPowerWattsPerCFM) = 1'>Expected 1 element(s) for xpath: extension/FanPowerWattsPerCFM</sch:assert>
<sch:assert role='ERROR' test='number(h:extension/h:FanPowerWattsPerCFM) &gt;= 0 or not(h:extension/h:FanPowerWattsPerCFM)'>Expected extension/FanPowerWattsPerCFM to be greater than or equal to 0</sch:assert>
Expand Down Expand Up @@ -864,6 +866,8 @@
<sch:assert role='ERROR' test='count(h:FractionCoolLoadServed) = 1'>Expected 1 element(s) for xpath: FractionCoolLoadServed</sch:assert>
<sch:assert role='ERROR' test='count(h:AnnualCoolingEfficiency[h:Units="SEER" or h:Units="SEER2"]/h:Value) = 1'>Expected 1 element(s) for xpath: AnnualCoolingEfficiency[Units="SEER" or Units="SEER2"]/Value</sch:assert>
<sch:assert role='ERROR' test='count(h:AnnualHeatingEfficiency[h:Units="HSPF" or h:Units="HSPF2"]/h:Value) = 1'>Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="HSPF" or Units="HSPF2"]/Value</sch:assert>
<sch:assert role='ERROR' test='count(h:CoolingDetailedPerformanceData) &lt;= 1'>Expected 0 or 1 element(s) for xpath: CoolingDetailedPerformanceData</sch:assert> <!-- See [CoolingDetailedPerformanceData] -->
<sch:assert role='ERROR' test='count(h:HeatingDetailedPerformanceData) &lt;= 1'>Expected 0 or 1 element(s) for xpath: HeatingDetailedPerformanceData</sch:assert> <!-- See [HeatingDetailedPerformanceData] -->
<sch:assert role='ERROR' test='count(h:extension/h:FanPowerWattsPerCFM) = 1'>Expected 1 element(s) for xpath: extension/FanPowerWattsPerCFM</sch:assert>
<sch:assert role='ERROR' test='number(h:extension/h:FanPowerWattsPerCFM) &gt;= 0 or not(h:extension/h:FanPowerWattsPerCFM)'>Expected extension/FanPowerWattsPerCFM to be greater than or equal to 0</sch:assert>
<sch:assert role='ERROR' test='count(h:extension/h:AirflowDefectRatio) = 1'>Expected 1 element(s) for xpath: extension/AirflowDefectRatio</sch:assert> <!-- See [AirflowDefectRatio] -->
Expand Down Expand Up @@ -896,6 +900,8 @@
<sch:assert role='ERROR' test='count(h:FractionCoolLoadServed) = 1'>Expected 1 element(s) for xpath: FractionCoolLoadServed</sch:assert>
<sch:assert role='ERROR' test='count(h:AnnualCoolingEfficiency[h:Units="SEER" or h:Units="SEER2"]/h:Value) = 1'>Expected 1 element(s) for xpath: AnnualCoolingEfficiency[Units="SEER" or Units="SEER2"]/Value</sch:assert>
<sch:assert role='ERROR' test='count(h:AnnualHeatingEfficiency[h:Units="HSPF" or h:Units="HSPF2"]/h:Value) = 1'>Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="HSPF" or Units="HSPF2"]/Value</sch:assert>
<sch:assert role='ERROR' test='count(h:CoolingDetailedPerformanceData) &lt;= 1'>Expected 0 or 1 element(s) for xpath: CoolingDetailedPerformanceData</sch:assert> <!-- See [CoolingDetailedPerformanceData] -->
<sch:assert role='ERROR' test='count(h:HeatingDetailedPerformanceData) &lt;= 1'>Expected 0 or 1 element(s) for xpath: HeatingDetailedPerformanceData</sch:assert> <!-- See [HeatingDetailedPerformanceData] -->
<sch:assert role='ERROR' test='count(h:extension/h:FanPowerWattsPerCFM) = 1'>Expected 1 element(s) for xpath: extension/FanPowerWattsPerCFM</sch:assert>
<sch:assert role='ERROR' test='number(h:extension/h:FanPowerWattsPerCFM) &gt;= 0 or not(h:extension/h:FanPowerWattsPerCFM)'>Expected extension/FanPowerWattsPerCFM to be greater than or equal to 0</sch:assert>
<sch:assert role='ERROR' test='count(h:extension/h:AirflowDefectRatio) = 1'>Expected 1 element(s) for xpath: extension/AirflowDefectRatio</sch:assert> <!-- See [AirflowDefectRatio] -->
Expand Down Expand Up @@ -1021,6 +1027,38 @@
</sch:rule>
</sch:pattern>

<sch:pattern>
<sch:title>[HeatingDetailedPerformanceData]</sch:title>
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Systems/h:HVAC/h:HVACPlant/*/h:HeatingDetailedPerformanceData'>
<sch:assert role='ERROR' test='count(../h:CompressorType[text()="variable speed"]) = 1'>Expected 1 element(s) for xpath: ../CompressorType[text()="variable speed"]</sch:assert>
<sch:assert role='ERROR' test='count(h:PerformanceDataPoint[h:OutdoorTemperature=47 and h:CapacityDescription="minimum"]) = 1'>Expected 1 element(s) for xpath: PerformanceDataPoint[OutdoorTemperature=47 and CapacityDescription="minimum"]</sch:assert> <!-- See [PerformanceDataPoint] -->
<sch:assert role='ERROR' test='count(h:PerformanceDataPoint[h:OutdoorTemperature=47 and h:CapacityDescription="maximum"]) = 1'>Expected 1 element(s) for xpath: PerformanceDataPoint[OutdoorTemperature=47 and CapacityDescription="maximum"]</sch:assert> <!-- See [PerformanceDataPoint] -->
<sch:assert role='ERROR' test='count(h:PerformanceDataPoint[h:OutdoorTemperature!=47 and h:CapacityDescription="minimum"]) &gt;= 1'>Expected 1 or more element(s) for xpath: PerformanceDataPoint[OutdoorTemperature!=47 and CapacityDescription="minimum"]</sch:assert> <!-- See [PerformanceDataPoint] -->
<sch:assert role='ERROR' test='count(h:PerformanceDataPoint[h:OutdoorTemperature!=47 and h:CapacityDescription="maximum"]) &gt;= 1'>Expected 1 or more element(s) for xpath: PerformanceDataPoint[OutdoorTemperature!=47 and CapacityDescription="maximum"]</sch:assert> <!-- See [PerformanceDataPoint] -->
</sch:rule>
</sch:pattern>

<sch:pattern>
<sch:title>[CoolingDetailedPerformanceData]</sch:title>
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Systems/h:HVAC/h:HVACPlant/*/h:CoolingDetailedPerformanceData'>
<sch:assert role='ERROR' test='count(../h:CompressorType[text()="variable speed"]) = 1'>Expected 1 element(s) for xpath: ../CompressorType[text()="variable speed"]</sch:assert>
<sch:assert role='ERROR' test='count(h:PerformanceDataPoint[h:OutdoorTemperature=95 and h:CapacityDescription="minimum"]) = 1'>Expected 1 element(s) for xpath: PerformanceDataPoint[OutdoorTemperature=95 and CapacityDescription="minimum"]</sch:assert> <!-- See [PerformanceDataPoint] -->
<sch:assert role='ERROR' test='count(h:PerformanceDataPoint[h:OutdoorTemperature=95 and h:CapacityDescription="maximum"]) = 1'>Expected 1 element(s) for xpath: PerformanceDataPoint[OutdoorTemperature=95 and CapacityDescription="maximum"]</sch:assert> <!-- See [PerformanceDataPoint] -->
<sch:assert role='ERROR' test='count(h:PerformanceDataPoint[h:OutdoorTemperature!=95 and h:CapacityDescription="minimum"]) &gt;= 1'>Expected 1 or more element(s) for xpath: PerformanceDataPoint[OutdoorTemperature!=95 and CapacityDescription="minimum"]</sch:assert> <!-- See [PerformanceDataPoint] -->
<sch:assert role='ERROR' test='count(h:PerformanceDataPoint[h:OutdoorTemperature!=95 and h:CapacityDescription="maximum"]) &gt;= 1'>Expected 1 or more element(s) for xpath: PerformanceDataPoint[OutdoorTemperature!=95 and CapacityDescription="maximum"]</sch:assert> <!-- See [PerformanceDataPoint] -->
</sch:rule>
</sch:pattern>

<sch:pattern>
<sch:title>[PerformanceDataPoint]</sch:title>
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Systems/h:HVAC/h:HVACPlant/*/*/h:PerformanceDataPoint'>
<sch:assert role='ERROR' test='count(h:Capacity) + count(h:CapacityFractionOfNominal) &gt;= 1'>Expected 1 or more element(s) for xpath: Capacity | CapacityFractionOfNominal</sch:assert>
<sch:assert role='ERROR' test='number(h:Capacity) &gt;= 0 or not(h:Capacity)'>Expected Capacity to be greater than or equal to 0</sch:assert>
<sch:assert role='ERROR' test='number(h:CapacityFractionOfNominal) &gt;= 0 or not(h:CapacityFractionOfNominal)'>Expected CapacityFractionOfNominal to be greater than or equal to 0</sch:assert>
<sch:assert role='ERROR' test='count(h:Efficiency[h:Units="COP"]/h:Value) = 1'>Expected 1 element(s) for xpath: Efficiency[Units="COP"]/Value</sch:assert>
</sch:rule>
</sch:pattern>

<sch:pattern>
<sch:title>[AirflowDefectRatio]</sch:title>
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Systems/h:HVAC/h:HVACPlant/*[not(h:DistributionSystem)]'>
Expand Down
36 changes: 36 additions & 0 deletions rulesets/tests/test_hvac.rb
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,42 @@ def test_dse
end
end

def test_air_to_air_heat_pump_var_speed_detailed_performance
hpxml_name = 'base-hvac-air-to-air-heat-pump-var-speed-detailed-performance.xml'
hpxml = HPXML.new(hpxml_path: File.join(@root_path, 'workflow', 'sample_files', hpxml_name))
hpxml_bldg = hpxml.buildings[0]
hpxml_name = File.basename(@tmp_hpxml_path)
XMLHelper.write_file(hpxml.to_doc, @tmp_hpxml_path)

_all_calc_types.each do |calc_type|
_hpxml, hpxml_bldg = _test_ruleset(hpxml_name, calc_type)
if [Constants.CalcTypeERIRatedHome].include? calc_type
assert_equal(6, hpxml_bldg.heat_pumps[-1].heating_detailed_performance_data.size)
assert_equal(4, hpxml_bldg.heat_pumps[-1].cooling_detailed_performance_data.size)
else
assert_equal(0, hpxml_bldg.heat_pumps[-1].heating_detailed_performance_data.size)
assert_equal(0, hpxml_bldg.heat_pumps[-1].cooling_detailed_performance_data.size)
end
end
end

def test_central_air_conditioner_var_speed_detailed_performance
hpxml_name = 'base-hvac-central-ac-only-var-speed-detailed-performance.xml'
hpxml = HPXML.new(hpxml_path: File.join(@root_path, 'workflow', 'sample_files', hpxml_name))
hpxml_bldg = hpxml.buildings[0]
hpxml_name = File.basename(@tmp_hpxml_path)
XMLHelper.write_file(hpxml.to_doc, @tmp_hpxml_path)

_all_calc_types.each do |calc_type|
_hpxml, hpxml_bldg = _test_ruleset(hpxml_name, calc_type)
if [Constants.CalcTypeERIRatedHome].include? calc_type
assert_equal(4, hpxml_bldg.cooling_systems[-1].cooling_detailed_performance_data.size)
else
assert_equal(0, hpxml_bldg.cooling_systems[-1].cooling_detailed_performance_data.size)
end
end
end

def _test_ruleset(hpxml_name, calc_type)
require_relative '../../workflow/design'
designs = [Design.new(calc_type: calc_type,
Expand Down
3 changes: 3 additions & 0 deletions tasks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2425,6 +2425,9 @@ def create_sample_hpxmls
'base-hvac-air-to-air-heat-pump-1-speed-seer2-hspf2.xml',
'base-hvac-air-to-air-heat-pump-2-speed.xml',
'base-hvac-air-to-air-heat-pump-var-speed.xml',
'base-hvac-air-to-air-heat-pump-var-speed-detailed-performance.xml',
'base-hvac-air-to-air-heat-pump-var-speed-detailed-performance-normalized-capacities.xml',
'base-hvac-central-ac-only-var-speed-detailed-performance.xml',
'base-hvac-boiler-elec-only.xml',
'base-hvac-boiler-gas-only.xml',
'base-hvac-boiler-oil-only.xml',
Expand Down
Loading