Skip to content

Commit

Permalink
Merge pull request #720 from NREL/ceiling-fan-watts
Browse files Browse the repository at this point in the history
Alternative ceiling fan watts input
  • Loading branch information
shorowit authored Feb 28, 2024
2 parents 9a230f5 + c39ef02 commit ce93f31
Show file tree
Hide file tree
Showing 8 changed files with 629 additions and 24 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ __New Features__
- Now defaults to -20F for `CompressorLockoutTemperature` for variable-speed air-to-air heat pumps.
- 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.

__Bugfixes__
- Fixes possible 301ruleset.rb error due to floating point arithmetic.
Expand Down
14 changes: 7 additions & 7 deletions docs/source/workflow_inputs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2632,13 +2632,13 @@ HPXML Ceiling Fans

Each ceiling fan is entered as a ``/HPXML/Building/BuildingDetails/Lighting/CeilingFan``.

========================================= ======= ======= =========== ======== ======== ==============================
Element Type Units Constraints Required Default Notes
========================================= ======= ======= =========== ======== ======== ==============================
``SystemIdentifier`` id Yes Unique identifier
``Airflow[FanSpeed="medium"]/Efficiency`` double cfm/W > 0 Yes Efficiency at medium speed
``Count`` integer > 0 Yes Number of similar ceiling fans
========================================= ======= ======= =========== ======== ======== ==============================
===================================================================== ======= ========== =========== ======== ======== ==============================
Element Type Units Constraints Required Default Notes
===================================================================== ======= ========== =========== ======== ======== ==============================
``SystemIdentifier`` id Yes Unique identifier
``Airflow[FanSpeed="medium"]/Efficiency`` and/or ``LabelEnergyUse`` double cfm/W or W > 0 Yes Efficiency at medium speed or EnergyGuide label average energy use
``Count`` integer > 0 Yes Number of similar ceiling fans
===================================================================== ======= ========== =========== ======== ======== ==============================

.. _hpxmllocations:

Expand Down
14 changes: 7 additions & 7 deletions rulesets/resources/301ruleset.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2286,9 +2286,8 @@ def self.set_ceiling_fans_reference(orig_bldg, new_bldg)
return
end

medium_cfm = 3000.0
new_bldg.ceiling_fans.add(id: 'CeilingFans',
efficiency: medium_cfm / HVAC.get_default_ceiling_fan_power(),
label_energy_use: HVAC.get_default_ceiling_fan_power(),
count: HVAC.get_default_ceiling_fan_quantity(@nbeds))
new_bldg.hvac_controls[0].ceiling_fan_cooling_setpoint_temp_offset = 0.5
end
Expand All @@ -2311,16 +2310,17 @@ def self.set_ceiling_fans_rated(orig_bldg, new_bldg)
orig_bldg.ceiling_fans.each do |orig_ceiling_fan|
num_cfs += orig_ceiling_fan.count
cfm_per_w = orig_ceiling_fan.efficiency
if cfm_per_w.nil?
fan_power_w = HVAC.get_default_ceiling_fan_power()
cfm_per_w = medium_cfm / fan_power_w
label_energy_use = orig_ceiling_fan.label_energy_use
if !label_energy_use.nil? # priority if both provided
sum_w += (label_energy_use * orig_ceiling_fan.count)
elsif !cfm_per_w.nil?
sum_w += (medium_cfm / cfm_per_w * orig_ceiling_fan.count)
end
sum_w += (medium_cfm / cfm_per_w * orig_ceiling_fan.count)
end
avg_w = sum_w / num_cfs

new_bldg.ceiling_fans.add(id: 'CeilingFans',
efficiency: medium_cfm / avg_w,
label_energy_use: avg_w,
count: HVAC.get_default_ceiling_fan_quantity(@nbeds))
new_bldg.hvac_controls[0].ceiling_fan_cooling_setpoint_temp_offset = 0.5
end
Expand Down
2 changes: 1 addition & 1 deletion rulesets/resources/301validator.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1694,7 +1694,7 @@
<sch:pattern>
<sch:title>[CeilingFan]</sch:title>
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Lighting/h:CeilingFan'>
<sch:assert role='ERROR' test='count(h:Airflow[h:FanSpeed="medium"]/h:Efficiency) = 1'>Expected 1 element(s) for xpath: Airflow[FanSpeed="medium"]/Efficiency</sch:assert>
<sch:assert role='ERROR' test='count(h:Airflow[h:FanSpeed="medium"]/h:Efficiency) + count(h:LabelEnergyUse) &gt;= 1'>Expected 1 or more element(s) for xpath: Airflow[FanSpeed="medium"]/Efficiency or LabelEnergyUse</sch:assert>
<sch:assert role='ERROR' test='count(h:Count) = 1'>Expected 1 element(s) for xpath: Count</sch:assert>
</sch:rule>
</sch:pattern>
Expand Down
92 changes: 83 additions & 9 deletions rulesets/tests/test_lighting.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ def test_lighting_pre_addendum_g
end

def test_ceiling_fans
# Efficiency

# Test w/ 301-2019
hpxml_name = 'base-lighting-ceiling-fans.xml'
hpxml = HPXML.new(hpxml_path: File.join(@root_path, 'workflow', 'sample_files', hpxml_name))
Expand All @@ -65,9 +67,9 @@ def test_ceiling_fans
_all_calc_types.each do |calc_type|
_hpxml, hpxml_bldg = _test_ruleset(hpxml_name, calc_type)
if [Constants.CalcTypeERIRatedHome].include? calc_type
_check_ceiling_fans(hpxml_bldg, cfm_per_w: 3000.0 / 30.0, count: 4)
_check_ceiling_fans(hpxml_bldg, label_energy_use: 30.0, count: 4)
else
_check_ceiling_fans(hpxml_bldg, cfm_per_w: 3000.0 / 42.6, count: 4)
_check_ceiling_fans(hpxml_bldg, label_energy_use: 42.6, count: 4)
end
end

Expand Down Expand Up @@ -95,9 +97,9 @@ def test_ceiling_fans
_all_calc_types.each do |calc_type|
_hpxml, hpxml_bldg = _test_ruleset(hpxml_name, calc_type)
if [Constants.CalcTypeERIRatedHome].include? calc_type
_check_ceiling_fans(hpxml_bldg, cfm_per_w: 3000.0 / 30.0, count: 4)
_check_ceiling_fans(hpxml_bldg, label_energy_use: 30.0, count: 4)
else
_check_ceiling_fans(hpxml_bldg, cfm_per_w: 3000.0 / 42.6, count: 4)
_check_ceiling_fans(hpxml_bldg, label_energy_use: 42.6, count: 4)
end
end

Expand All @@ -113,11 +115,78 @@ def test_ceiling_fans
_all_calc_types.each do |calc_type|
_hpxml, hpxml_bldg = _test_ruleset(hpxml_name, calc_type)
if [Constants.CalcTypeERIReferenceHome, Constants.CalcTypeCO2eReferenceHome].include? calc_type
_check_ceiling_fans(hpxml_bldg, cfm_per_w: 3000.0 / 42.6, count: 6)
_check_ceiling_fans(hpxml_bldg, label_energy_use: 42.6, count: 6)
elsif [Constants.CalcTypeERIRatedHome].include? calc_type
_check_ceiling_fans(hpxml_bldg, label_energy_use: 30.0, count: 6)
else
_check_ceiling_fans(hpxml_bldg, label_energy_use: 42.6, count: 4)
end
end

# Label energy use

# Test w/ 301-2019
hpxml_name = 'base-lighting-ceiling-fans-label-energy-use.xml'
hpxml = HPXML.new(hpxml_path: File.join(@root_path, 'workflow', 'sample_files', hpxml_name))
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
_check_ceiling_fans(hpxml_bldg, label_energy_use: 39.0, count: 4)
else
_check_ceiling_fans(hpxml_bldg, label_energy_use: 42.6, count: 4)
end
end

# Test w/ 301-2019 and Nfans < Nbr + 1
hpxml_name = 'base-lighting-ceiling-fans-label-energy-use.xml'
hpxml = HPXML.new(hpxml_path: File.join(@root_path, 'workflow', 'sample_files', hpxml_name))
hpxml_bldg = hpxml.buildings[0]
hpxml_bldg.ceiling_fans[0].count = 3
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)
_check_ceiling_fans(hpxml_bldg)
end

# Test w/ 301-2014 and Nfans < Nbr + 1
hpxml_name = _change_eri_version('base-lighting-ceiling-fans-label-energy-use.xml', '2014')
hpxml = HPXML.new(hpxml_path: File.join(@root_path, 'workflow', 'sample_files', hpxml_name))
hpxml_bldg = hpxml.buildings[0]
hpxml_bldg.ceiling_fans[0].count = 3
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
_check_ceiling_fans(hpxml_bldg, label_energy_use: 39.0, count: 4)
else
_check_ceiling_fans(hpxml_bldg, label_energy_use: 42.6, count: 4)
end
end

# Test w/ different Nbr
hpxml_name = 'base-lighting-ceiling-fans-label-energy-use.xml'
hpxml = HPXML.new(hpxml_path: File.join(@root_path, 'workflow', 'sample_files', hpxml_name))
hpxml_bldg = hpxml.buildings[0]
hpxml_bldg.building_construction.number_of_bedrooms = 5
hpxml_bldg.ceiling_fans[0].count = 6
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.CalcTypeERIReferenceHome, Constants.CalcTypeCO2eReferenceHome].include? calc_type
_check_ceiling_fans(hpxml_bldg, label_energy_use: 42.6, count: 6)
elsif [Constants.CalcTypeERIRatedHome].include? calc_type
_check_ceiling_fans(hpxml_bldg, cfm_per_w: 3000.0 / 30.0, count: 6)
_check_ceiling_fans(hpxml_bldg, label_energy_use: 39.0, count: 6)
else
_check_ceiling_fans(hpxml_bldg, cfm_per_w: 3000.0 / 42.6, count: 4)
_check_ceiling_fans(hpxml_bldg, label_energy_use: 42.6, count: 4)
end
end
end
Expand Down Expand Up @@ -196,13 +265,18 @@ def _check_lighting(hpxml_bldg, f_int_cfl: nil, f_ext_cfl: nil, f_grg_cfl: nil,
end
end

def _check_ceiling_fans(hpxml_bldg, cfm_per_w: nil, count: nil)
if cfm_per_w.nil? && count.nil?
def _check_ceiling_fans(hpxml_bldg, label_energy_use: nil, cfm_per_w: nil, count: nil)
if label_energy_use.nil? && cfm_per_w.nil? && count.nil?
assert_equal(0, hpxml_bldg.ceiling_fans.size)
assert_nil(hpxml_bldg.hvac_controls[0].ceiling_fan_cooling_setpoint_temp_offset)
else
assert_equal(1, hpxml_bldg.ceiling_fans.size)
ceiling_fan = hpxml_bldg.ceiling_fans[0]
if label_energy_use.nil?
assert_nil(ceiling_fan.label_energy_use)
else
assert_equal(label_energy_use, ceiling_fan.label_energy_use)
end
if cfm_per_w.nil?
assert_nil(ceiling_fan.efficiency)
else
Expand Down
1 change: 1 addition & 0 deletions tasks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2476,6 +2476,7 @@ def create_sample_hpxmls
'base-hvac-undersized.xml',
'base-hvac-wall-furnace-elec-only.xml',
'base-lighting-ceiling-fans.xml',
'base-lighting-ceiling-fans-label-energy-use.xml',
'base-location-baltimore-md.xml',
'base-location-capetown-zaf.xml',
'base-location-dallas-tx.xml',
Expand Down
Loading

0 comments on commit ce93f31

Please sign in to comment.