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