diff --git a/Changelog.md b/Changelog.md
index 0e8981dd0..358854417 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,7 +2,8 @@
__New Features__
- Implements ANSI/RESNET/ICC Standard 301-2022 and Addendum C.
- - ERICalculation/Version and CO2IndexCalculation/Version can now be "2022C" or "2022"
+ - ERICalculation/Version and CO2IndexCalculation/Version can now be "2022C" or "2022".
+ - Allows modeling electric battery storage ("2022C" or newer).
- Ground source heat pump model enhancements.
- Allows `Roof/RadiantBarrier` to be omitted; defaults to false.
- Adds more error-checking for inappropriate inputs (e.g., HVAC SHR=0 or clothes washer IMEF=0).
diff --git a/docs/source/workflow_inputs.rst b/docs/source/workflow_inputs.rst
index dc0466f81..ae604f2a9 100644
--- a/docs/source/workflow_inputs.rst
+++ b/docs/source/workflow_inputs.rst
@@ -1976,6 +1976,35 @@ In addition, an inverter must be entered as a ``/HPXML/Building/BuildingDetails/
.. [#] For homes with multiple inverters, all InverterEfficiency elements must have the same value.
.. [#] Default from PVWatts is 0.96.
+HPXML Batteries
+***************
+
+A single battery can be entered as a ``/HPXML/Building/BuildingDetails/Systems/Batteries/Battery``.
+
+ ==================================================== ======= ========= ======================= ======== ======== ============================================
+ Element Type Units Constraints Required Default Notes
+ ==================================================== ======= ========= ======================= ======== ======== ============================================
+ ``SystemIdentifier`` id Yes Unique identifier
+ ``Location`` string See [#]_ No See [#]_ Location
+ ``BatteryType`` string See [#]_ Yes Battery type
+ ``NominalCapacity[Units="kWh"]/Value`` double kWh >= 0 Yes Nominal (total) capacity
+ ``UsableCapacity[Units="kWh"]/Value`` double kWh >= 0, < NominalCapacity Yes Usable capacity
+ ``RatedPowerOutput`` double W >= 0 Yes Power output under non-peak conditions
+ ``RoundTripEfficiency`` double frac >0, <= 1 Yes Round trip efficiency
+ ==================================================== ======= ========= ======================= ======== ======== ============================================
+
+ .. [#] Location choices are "conditioned space", "basement - conditioned", "basement - unconditioned", "crawlspace - vented", "crawlspace - unvented", "attic - vented", "attic - unvented", "garage", or "outside".
+ .. [#] If Location not provided, defaults to "garage" if a garage is present, otherwise "outside".
+ .. [#] BatteryType only choice is "Li-ion".
+
+.. note::
+
+ The battery will charge if PV production is greater than the building load and the battery is below its maximum capacity.
+ The battery will discharge if the building load is greater than the PV production and the battery is above its minimum capacity.
+ A battery in a home without PV is not modeled.
+
+ For ERI calculations, batteries will result in a small penalty because ERI is calculated using annual energy consumption and batteries increase annual electricity consumption (due to round trip efficiency).
+ For CO2e Index calculations, batteries can result in a credit because CO2e Index is calculated using hourly electricity emissions factors and batteries shift when electricity consumption occurs.
HPXML Generators
****************
diff --git a/rulesets/resources/301ruleset.rb b/rulesets/resources/301ruleset.rb
index b03b698bd..97a88e6e6 100644
--- a/rulesets/resources/301ruleset.rb
+++ b/rulesets/resources/301ruleset.rb
@@ -1899,14 +1899,18 @@ def self.set_systems_batteries_reference(orig_bldg, new_bldg)
end
def self.set_systems_batteries_rated(orig_bldg, new_bldg)
- # Temporarily disabled until RESNET allows this.
- # orig_bldg.batteries.each do |orig_battery|
- # new_bldg.batteries.add(id: orig_battery.id,
- # type: orig_battery.type,
- # location: orig_battery.location,
- # nominal_capacity_kwh: orig_battery.nominal_capacity_kwh,
- # usable_capacity_kwh: orig_battery.usable_capacity_kwh)
- # end
+ if Constants.ERIVersions.index(@eri_version) >= Constants.ERIVersions.index('2022C')
+ # FIXME: Need to pro-rate if a shared battery.
+ orig_bldg.batteries.each do |orig_battery|
+ new_bldg.batteries.add(id: orig_battery.id,
+ type: orig_battery.type,
+ location: orig_battery.location,
+ nominal_capacity_kwh: orig_battery.nominal_capacity_kwh,
+ usable_capacity_kwh: orig_battery.usable_capacity_kwh,
+ rated_power_output: orig_battery.rated_power_output,
+ round_trip_efficiency: orig_battery.round_trip_efficiency)
+ end
+ end
end
def self.set_systems_batteries_iad(orig_bldg, new_bldg)
diff --git a/rulesets/resources/301validator.xml b/rulesets/resources/301validator.xml
index 79c2fc4da..b5f81efe7 100644
--- a/rulesets/resources/301validator.xml
+++ b/rulesets/resources/301validator.xml
@@ -187,10 +187,7 @@
Expected 0 or more element(s) for xpath: Systems/WaterHeating/WaterFixture
Expected 0 or 1 element(s) for xpath: Systems/SolarThermal/SolarThermalSystem
Expected 0 or more element(s) for xpath: Systems/Photovoltaics/PVSystem
-
Expected 0 or more element(s) for xpath: Systems/extension/Generators/Generator
Expected 0 or 1 element(s) for xpath: Appliances/ClothesWasher
Expected 0 or 1 element(s) for xpath: Appliances/ClothesDryer
@@ -1406,8 +1403,6 @@ Temporarily disabled until RESNET allows this.
-
+ Rated power output should typically be greater than or equal to 1000 W.
--->
[Generator]
diff --git a/rulesets/tests/test_es_zerh_pv_batteries.rb b/rulesets/tests/test_es_zerh_pv_batteries.rb
index b0d52df0c..6265d9515 100644
--- a/rulesets/tests/test_es_zerh_pv_batteries.rb
+++ b/rulesets/tests/test_es_zerh_pv_batteries.rb
@@ -30,7 +30,6 @@ def test_pv
end
def test_pv_batteries
- skip # Temporarily disabled until RESNET allows this.
[*ESConstants.AllVersions, *ZERHConstants.AllVersions].each do |program_version|
_convert_to_es_zerh('base-pv-battery.xml', program_version)
_hpxml, hpxml_bldg = _test_ruleset(program_version)
diff --git a/rulesets/tests/test_pv_batteries.rb b/rulesets/tests/test_pv_batteries.rb
index 5e3884af8..ac1ee28f6 100644
--- a/rulesets/tests/test_pv_batteries.rb
+++ b/rulesets/tests/test_pv_batteries.rb
@@ -49,13 +49,12 @@ def test_pv_shared
end
def test_pv_batteries
- skip # Temporarily disabled until RESNET allows this.
hpxml_name = 'base-pv-battery.xml'
_all_calc_types.each do |calc_type|
_hpxml, hpxml_bldg = _test_ruleset(hpxml_name, calc_type)
if [Constants.CalcTypeERIRatedHome].include? calc_type
- _check_battery(hpxml_bldg, [{ type: HPXML::BatteryTypeLithiumIon, location: HPXML::LocationOutside, nominal_capacity_kwh: 20.0, usable_capacity_kwh: 18.0 }])
+ _check_battery(hpxml_bldg, [{ type: HPXML::BatteryTypeLithiumIon, location: HPXML::LocationOutside, nominal_capacity_kwh: 20.0, usable_capacity_kwh: 18.0, rated_power_output: 6000, round_trip_efficiency: 0.925 }])
else
_check_battery(hpxml_bldg)
end
@@ -113,6 +112,8 @@ def _check_battery(hpxml_bldg, all_expected_values = [])
assert_equal(expected_values[:location], battery.location)
assert_equal(expected_values[:nominal_capacity_kwh], battery.nominal_capacity_kwh)
assert_equal(expected_values[:usable_capacity_kwh], battery.usable_capacity_kwh)
+ assert_equal(expected_values[:rated_power_output], battery.rated_power_output)
+ assert_equal(expected_values[:round_trip_efficiency], battery.round_trip_efficiency)
end
end
end
diff --git a/tasks.rb b/tasks.rb
index 12afe6ffb..0c27fc787 100644
--- a/tasks.rb
+++ b/tasks.rb
@@ -2347,7 +2347,7 @@ def create_sample_hpxmls
'base-atticroof-radiant-barrier.xml',
'base-atticroof-unvented-insulated-roof.xml',
'base-atticroof-vented.xml',
- # 'base-battery.xml',
+ 'base-battery.xml',
'base-bldgtype-mf-unit.xml',
'base-bldgtype-mf-unit-adjacent-to-multiple.xml',
'base-bldgtype-mf-unit-shared-boiler-only-baseboard.xml',
@@ -2500,8 +2500,8 @@ def create_sample_hpxmls
'base-mechvent-supply.xml',
'base-mechvent-whole-house-fan.xml',
'base-misc-generators.xml',
- 'base-pv.xml']
- # 'base-pv-battery.xml']
+ 'base-pv.xml',
+ 'base-pv-battery.xml']
include_list.each do |include_file|
if File.exist? "hpxml-measures/workflow/sample_files/#{include_file}"
FileUtils.cp("hpxml-measures/workflow/sample_files/#{include_file}", "workflow/sample_files/#{include_file}")
@@ -2795,6 +2795,10 @@ def create_sample_hpxmls
fail hpxml_path
end
end
+ hpxml_bldg.batteries.each do |battery|
+ battery.location = nil
+ battery.round_trip_efficiency = 0.925
+ end
zip_map = { 'USA_CO_Denver.Intl.AP.725650_TMY3.epw' => '80206',
'USA_OR_Portland.Intl.AP.726980_TMY3.epw' => '97214',
'US_CO_Boulder_AMY_2012.epw' => '80305-3447',
diff --git a/workflow/energy_rating_index.rb b/workflow/energy_rating_index.rb
index 71b3cc0a4..17dfd6647 100644
--- a/workflow/energy_rating_index.rb
+++ b/workflow/energy_rating_index.rb
@@ -473,7 +473,8 @@ def get_eec(system, type, is_dfhp_primary = nil)
generation_elec_produced = get_end_use(rated_output, EUT::Generator, FT::Elec)
generation_fuel_consumed = get_end_use(rated_output, EUT::Generator, non_elec_fuels)
results[:opp] = calculate_opp(renewable_energy_limit, renewable_elec_produced, generation_elec_produced, generation_fuel_consumed)
- results[:pefrac] = calculate_pefrac(results[:teu], results[:opp])
+ results[:bsl] = get_end_use(rated_output, EUT::Battery, FT::Elec)
+ results[:pefrac] = calculate_pefrac(results[:teu], results[:opp], results[:bsl])
results[:eul_dh] = calculate_dh(rated_output)
results[:eul_mv] = calculate_mv(rated_output)
@@ -508,7 +509,8 @@ def get_eec(system, type, is_dfhp_primary = nil)
results[:eri_cool].map { |c| c.ec_x }.sum(0.0) +
results[:eri_dhw].map { |c| c.ec_x }.sum(0.0) +
results[:eul_la] + results[:eul_mv] + results[:eul_dh] + whf_energy +
- renewable_elec_produced + generation_elec_produced + generation_fuel_consumed
+ renewable_elec_produced + generation_elec_produced + generation_fuel_consumed +
+ results[:bsl]
total_ec_x = get_fuel_use(rated_output, all_fuels, use_net: true)
if (sum_ec_x - total_ec_x).abs > 0.1
fail "Sum of energy consumptions (#{sum_ec_x.round(2)}) do not match total (#{total_ec_x.round(2)}) for Rated Home."
@@ -722,10 +724,10 @@ def calculate_opp(renewable_energy_limit, renewable_elec_produced, generation_el
return opp
end
-def calculate_pefrac(teu, opp)
+def calculate_pefrac(teu, opp, bsl)
pefrac = 1.0
if teu > 0
- pefrac = (teu - opp) / teu
+ pefrac = (teu - opp + bsl) / teu
end
return pefrac
end
diff --git a/workflow/sample_files/base-battery.xml b/workflow/sample_files/base-battery.xml
new file mode 100644
index 000000000..8c15d7a99
--- /dev/null
+++ b/workflow/sample_files/base-battery.xml
@@ -0,0 +1,527 @@
+
+
+
+ HPXML
+ tasks.rb
+ 2000-01-01T00:00:00-07:00
+ create
+
+
+
+
+ latest
+
+
+ latest
+
+
+ SF_National_3.2
+
+
+ 2021
+
+
+ SF_2.0
+
+
+
+
+
+
+
+
+ CO
+ 80206
+
+
+
+ proposed workscope
+
+
+
+
+
+ electricity
+ natural gas
+
+
+
+ single-family detached
+ 2.0
+ 1.0
+ 3
+ 2700.0
+
+
+
+
+ 2006
+ 5B
+
+
+ 2021
+ 5B
+
+
+
+ USA_CO_Denver.Intl.AP.725650_TMY3
+
+ USA_CO_Denver.Intl.AP.725650_TMY3.epw
+
+
+
+
+
+
+
+ 50.0
+
+ ACH
+ 3.0
+
+ 21600.0
+
+
+
+
+
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+ attic - unvented
+ 1509.3
+ 0.7
+ 0.92
+ 6.0
+
+
+ 2.3
+
+
+
+
+
+
+ outside
+ basement - conditioned
+ 115.6
+ 0.7
+ 0.92
+
+
+ 23.0
+
+
+
+
+
+
+ outside
+ conditioned space
+
+
+
+ 1200.0
+ 0.7
+ 0.92
+
+
+ 23.0
+
+
+
+
+ outside
+ attic - unvented
+
+
+
+ 225.0
+ 0.7
+ 0.92
+
+
+ 4.0
+
+
+
+
+
+
+ ground
+ basement - conditioned
+ 8.0
+ 1200.0
+ 8.0
+ 7.0
+
+
+
+ continuous - exterior
+ 8.9
+ 0.0
+ 8.0
+
+
+ continuous - interior
+ 0.0
+ 0.0
+ 0.0
+
+
+
+
+
+
+
+ attic - unvented
+ conditioned space
+
+
+
+ 1350.0
+
+
+ 39.3
+
+
+
+
+
+
+ basement - conditioned
+ 1350.0
+ 4.0
+ 150.0
+
+
+
+ 0.0
+ 0.0
+
+
+
+
+
+ 0.0
+ 0.0
+
+
+
+ 0.0
+ 0.0
+
+
+
+
+
+
+ 108.0
+ 0
+ 0.33
+ 0.45
+ 0.67
+
+
+
+
+ 72.0
+ 90
+ 0.33
+ 0.45
+ 0.67
+
+
+
+
+ 108.0
+ 180
+ 0.33
+ 0.45
+ 0.67
+
+
+
+
+ 72.0
+ 270
+ 0.33
+ 0.45
+ 0.67
+
+
+
+
+
+
+
+ 40.0
+ 180
+ 4.4
+
+
+
+
+
+
+
+
+
+
+
+
+ natural gas
+ 36000.0
+
+ AFUE
+ 0.92
+
+ 1.0
+
+ 0.58
+ -0.25
+
+
+
+
+
+ central air conditioner
+ electricity
+ 24000.0
+ single stage
+ 1.0
+
+ SEER
+ 13.0
+
+ 0.73
+
+ -0.25
+ -0.25
+ 0.58
+
+
+
+
+
+ manual thermostat
+
+
+
+
+
+ regular velocity
+
+ supply
+
+ CFM25
+ 75.0
+ to outside
+
+
+
+ return
+
+ CFM25
+ 25.0
+ to outside
+
+
+
+
+ supply
+ 4.0
+ attic - unvented
+ 150.0
+
+
+
+ return
+ 0.0
+ attic - unvented
+ 50.0
+
+ 2
+
+
+ 2700.0
+
+
+
+
+
+ electricity
+ storage water heater
+ conditioned space
+ false
+ 40.0
+ 1.0
+ 18767.0
+ 0.95
+
+
+
+
+
+ 50.0
+
+
+
+ 0.0
+
+
+
+
+ shower head
+ true
+
+
+
+ faucet
+ false
+
+
+
+
+
+ Li-ion
+
+ kWh
+ 20.0
+
+
+ kWh
+ 18.0
+
+ 6000.0
+ 0.925
+
+
+
+
+
+
+ false
+ conditioned space
+ 1.21
+ 380.0
+ 0.12
+ 1.09
+ 27.0
+ 6.0
+ 3.2
+
+
+
+ false
+ conditioned space
+ electricity
+ 3.73
+ true
+ 150.0
+
+
+
+ false
+ conditioned space
+ 307.0
+ 12
+ 0.12
+ 1.09
+ 22.32
+ 4.0
+
+
+
+ conditioned space
+ 650.0
+ true
+
+
+
+ conditioned space
+ electricity
+ false
+
+
+
+ false
+
+
+
+
+
+ interior
+ 0.4
+
+
+
+
+
+
+ interior
+ 0.1
+
+
+
+
+
+
+ interior
+ 0.25
+
+
+
+
+
+
+ exterior
+ 0.4
+
+
+
+
+
+
+ exterior
+ 0.1
+
+
+
+
+
+
+ exterior
+ 0.25
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/workflow/sample_files/base-pv-battery.xml b/workflow/sample_files/base-pv-battery.xml
new file mode 100644
index 000000000..a78e6e1ff
--- /dev/null
+++ b/workflow/sample_files/base-pv-battery.xml
@@ -0,0 +1,557 @@
+
+
+
+ HPXML
+ tasks.rb
+ 2000-01-01T00:00:00-07:00
+ create
+
+
+
+
+ latest
+
+
+ latest
+
+
+ SF_National_3.2
+
+
+ 2021
+
+
+ SF_2.0
+
+
+
+
+
+
+
+
+ CO
+ 80206
+
+
+
+ proposed workscope
+
+
+
+
+
+ electricity
+ natural gas
+
+
+
+ single-family detached
+ 2.0
+ 1.0
+ 3
+ 2700.0
+
+
+
+
+ 2006
+ 5B
+
+
+ 2021
+ 5B
+
+
+
+ USA_CO_Denver.Intl.AP.725650_TMY3
+
+ USA_CO_Denver.Intl.AP.725650_TMY3.epw
+
+
+
+
+
+
+
+ 50.0
+
+ ACH
+ 3.0
+
+ 21600.0
+
+
+
+
+
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+ attic - unvented
+ 1509.3
+ 0.7
+ 0.92
+ 6.0
+
+
+ 2.3
+
+
+
+
+
+
+ outside
+ basement - conditioned
+ 115.6
+ 0.7
+ 0.92
+
+
+ 23.0
+
+
+
+
+
+
+ outside
+ conditioned space
+
+
+
+ 1200.0
+ 0.7
+ 0.92
+
+
+ 23.0
+
+
+
+
+ outside
+ attic - unvented
+
+
+
+ 225.0
+ 0.7
+ 0.92
+
+
+ 4.0
+
+
+
+
+
+
+ ground
+ basement - conditioned
+ 8.0
+ 1200.0
+ 8.0
+ 7.0
+
+
+
+ continuous - exterior
+ 8.9
+ 0.0
+ 8.0
+
+
+ continuous - interior
+ 0.0
+ 0.0
+ 0.0
+
+
+
+
+
+
+
+ attic - unvented
+ conditioned space
+
+
+
+ 1350.0
+
+
+ 39.3
+
+
+
+
+
+
+ basement - conditioned
+ 1350.0
+ 4.0
+ 150.0
+
+
+
+ 0.0
+ 0.0
+
+
+
+
+
+ 0.0
+ 0.0
+
+
+
+ 0.0
+ 0.0
+
+
+
+
+
+
+ 108.0
+ 0
+ 0.33
+ 0.45
+ 0.67
+
+
+
+
+ 72.0
+ 90
+ 0.33
+ 0.45
+ 0.67
+
+
+
+
+ 108.0
+ 180
+ 0.33
+ 0.45
+ 0.67
+
+
+
+
+ 72.0
+ 270
+ 0.33
+ 0.45
+ 0.67
+
+
+
+
+
+
+
+ 40.0
+ 180
+ 4.4
+
+
+
+
+
+
+
+
+
+
+
+
+ natural gas
+ 36000.0
+
+ AFUE
+ 0.92
+
+ 1.0
+
+ 0.58
+ -0.25
+
+
+
+
+
+ central air conditioner
+ electricity
+ 24000.0
+ single stage
+ 1.0
+
+ SEER
+ 13.0
+
+ 0.73
+
+ -0.25
+ -0.25
+ 0.58
+
+
+
+
+
+ manual thermostat
+
+
+
+
+
+ regular velocity
+
+ supply
+
+ CFM25
+ 75.0
+ to outside
+
+
+
+ return
+
+ CFM25
+ 25.0
+ to outside
+
+
+
+
+ supply
+ 4.0
+ attic - unvented
+ 150.0
+
+
+
+ return
+ 0.0
+ attic - unvented
+ 50.0
+
+ 2
+
+
+ 2700.0
+
+
+
+
+
+ electricity
+ storage water heater
+ conditioned space
+ false
+ 40.0
+ 1.0
+ 18767.0
+ 0.95
+
+
+
+
+
+ 50.0
+
+
+
+ 0.0
+
+
+
+
+ shower head
+ true
+
+
+
+ faucet
+ false
+
+
+
+
+
+ false
+ roof
+ standard
+ fixed
+ 180
+ 20.0
+ 4000.0
+ 0.14
+
+
+
+
+ false
+ roof
+ premium
+ fixed
+ 90
+ 20.0
+ 1500.0
+ 0.14
+
+
+
+
+ 0.96
+
+
+
+
+
+ Li-ion
+
+ kWh
+ 20.0
+
+
+ kWh
+ 18.0
+
+ 6000.0
+ 0.925
+
+
+
+
+
+
+ false
+ conditioned space
+ 1.21
+ 380.0
+ 0.12
+ 1.09
+ 27.0
+ 6.0
+ 3.2
+
+
+
+ false
+ conditioned space
+ electricity
+ 3.73
+ true
+ 150.0
+
+
+
+ false
+ conditioned space
+ 307.0
+ 12
+ 0.12
+ 1.09
+ 22.32
+ 4.0
+
+
+
+ conditioned space
+ 650.0
+ true
+
+
+
+ conditioned space
+ electricity
+ false
+
+
+
+ false
+
+
+
+
+
+ interior
+ 0.4
+
+
+
+
+
+
+ interior
+ 0.1
+
+
+
+
+
+
+ interior
+ 0.25
+
+
+
+
+
+
+ exterior
+ 0.4
+
+
+
+
+
+
+ exterior
+ 0.1
+
+
+
+
+
+
+ exterior
+ 0.25
+
+
+
+
+
+
+
+
\ No newline at end of file