Skip to content

Commit fddd2df

Browse files
authored
Merge pull request #1179 from NREL/attached_dhw_dist
Attach shared appliances to DHW distribution
2 parents 1a12948 + 2da3ebe commit fddd2df

12 files changed

Lines changed: 635 additions & 64 deletions

File tree

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ __New Features__
2121
- Adds optional arguments for utility bill scenarios.
2222
- ReportUtilityBills measure:
2323
- Removes utility rate and PV related arguments in lieu of new utility bill scenarios described inside the HPXML file.
24+
- Allows shared dishwasher/clothes washer to be attached to a hot water distribution system instead of a single water heater.
2425

2526
__Bugfixes__
2627
- Fixes possible incorrect autosizing of heat pump *separate* backup systems with respect to duct loads.

HPXMLtoOpenStudio/measure.xml

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
<schema_version>3.0</schema_version>
44
<name>hpxm_lto_openstudio</name>
55
<uid>b1543b30-9465-45ff-ba04-1d1f85e763bc</uid>
6-
<version_id>700496d3-089d-489d-a2cc-ad09d7869d03</version_id>
7-
<version_modified>20220915T180012Z</version_modified>
6+
<version_id>6a814a43-be01-41c7-9bdc-d6c9c9784f9b</version_id>
7+
<version_modified>20220919T151913Z</version_modified>
88
<xml_checksum>D8922A73</xml_checksum>
99
<class_name>HPXMLtoOpenStudio</class_name>
1010
<display_name>HPXML to OpenStudio Translator</display_name>
@@ -337,12 +337,6 @@
337337
<usage_type>resource</usage_type>
338338
<checksum>500A5756</checksum>
339339
</file>
340-
<file>
341-
<filename>hotwater_appliances.rb</filename>
342-
<filetype>rb</filetype>
343-
<usage_type>resource</usage_type>
344-
<checksum>9764D005</checksum>
345-
</file>
346340
<file>
347341
<filename>meta_measure.rb</filename>
348342
<filetype>rb</filetype>
@@ -535,12 +529,6 @@
535529
<usage_type>resource</usage_type>
536530
<checksum>4D0D827D</checksum>
537531
</file>
538-
<file>
539-
<filename>hpxml_schematron/EPvalidator.xml</filename>
540-
<filetype>xml</filetype>
541-
<usage_type>resource</usage_type>
542-
<checksum>B6BC6A9D</checksum>
543-
</file>
544532
<file>
545533
<filename>test_airflow.rb</filename>
546534
<filetype>rb</filetype>
@@ -570,12 +558,6 @@
570558
<usage_type>script</usage_type>
571559
<checksum>4F98F3F7</checksum>
572560
</file>
573-
<file>
574-
<filename>hpxml.rb</filename>
575-
<filetype>rb</filetype>
576-
<usage_type>resource</usage_type>
577-
<checksum>0D60DE1E</checksum>
578-
</file>
579561
<file>
580562
<filename>test_defaults.rb</filename>
581563
<filetype>rb</filetype>
@@ -588,11 +570,29 @@
588570
<usage_type>resource</usage_type>
589571
<checksum>6ED20DA1</checksum>
590572
</file>
573+
<file>
574+
<filename>hotwater_appliances.rb</filename>
575+
<filetype>rb</filetype>
576+
<usage_type>resource</usage_type>
577+
<checksum>1BAC39B2</checksum>
578+
</file>
579+
<file>
580+
<filename>hpxml_schematron/EPvalidator.xml</filename>
581+
<filetype>xml</filetype>
582+
<usage_type>resource</usage_type>
583+
<checksum>D133B230</checksum>
584+
</file>
591585
<file>
592586
<filename>test_validation.rb</filename>
593587
<filetype>rb</filetype>
594588
<usage_type>test</usage_type>
595-
<checksum>84BC4702</checksum>
589+
<checksum>F01525B5</checksum>
590+
</file>
591+
<file>
592+
<filename>hpxml.rb</filename>
593+
<filetype>rb</filetype>
594+
<usage_type>resource</usage_type>
595+
<checksum>FBEFBFF9</checksum>
596596
</file>
597597
</files>
598598
</measure>

HPXMLtoOpenStudio/resources/hotwater_appliances.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,9 @@ def self.apply(model, runner, hpxml, weather, spaces, hot_water_distribution,
309309
# Clothes washer
310310
if not clothes_washer.nil?
311311
gpd_frac = nil
312-
if clothes_washer.is_shared_appliance && clothes_washer.water_heating_system.id == water_heating_system.id
312+
if clothes_washer.is_shared_appliance && (not clothes_washer.hot_water_distribution.nil?)
313+
gpd_frac = 1.0 / hpxml.water_heating_systems.size # Apportion load to each water heater on distribution system
314+
elsif clothes_washer.is_shared_appliance && clothes_washer.water_heating_system.id == water_heating_system.id
313315
gpd_frac = 1.0 # Shared water heater sees full appliance load
314316
elsif not clothes_washer.is_shared_appliance
315317
gpd_frac = water_heating_system.fraction_dhw_load_served
@@ -333,7 +335,9 @@ def self.apply(model, runner, hpxml, weather, spaces, hot_water_distribution,
333335
next unless not dishwasher.nil?
334336

335337
gpd_frac = nil
336-
if dishwasher.is_shared_appliance && dishwasher.water_heating_system.id == water_heating_system.id
338+
if dishwasher.is_shared_appliance && (not dishwasher.hot_water_distribution.nil?)
339+
gpd_frac = 1.0 / hpxml.water_heating_systems.size # Apportion load to each water heater on distribution system
340+
elsif dishwasher.is_shared_appliance && dishwasher.water_heating_system.id == water_heating_system.id
337341
gpd_frac = 1.0 # Shared water heater sees full appliance load
338342
elsif not dishwasher.is_shared_appliance
339343
gpd_frac = water_heating_system.fraction_dhw_load_served

HPXMLtoOpenStudio/resources/hpxml.rb

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5236,8 +5236,8 @@ class ClothesWasher < BaseElement
52365236
ATTRS = [:id, :location, :modified_energy_factor, :integrated_modified_energy_factor,
52375237
:rated_annual_kwh, :label_electric_rate, :label_gas_rate, :label_annual_gas_cost,
52385238
:capacity, :label_usage, :usage_multiplier, :is_shared_appliance, :number_of_units,
5239-
:number_of_units_served, :water_heating_system_idref, :weekday_fractions,
5240-
:weekend_fractions, :monthly_multipliers]
5239+
:number_of_units_served, :water_heating_system_idref, :hot_water_distribution_idref,
5240+
:weekday_fractions, :weekend_fractions, :monthly_multipliers]
52415241

52425242
attr_accessor(*ATTRS)
52435243

@@ -5252,13 +5252,25 @@ def water_heating_system
52525252
fail "Attached water heating system '#{@water_heating_system_idref}' not found for clothes washer '#{@id}'."
52535253
end
52545254

5255+
def hot_water_distribution
5256+
return if @hot_water_distribution_idref.nil?
5257+
5258+
@hpxml_object.hot_water_distributions.each do |hot_water_distribution|
5259+
next unless hot_water_distribution.id == @hot_water_distribution_idref
5260+
5261+
return hot_water_distribution
5262+
end
5263+
fail "Attached hot water distribution '#{@hot_water_distribution_idref}' not found for clothes washer '#{@id}'."
5264+
end
5265+
52555266
def delete
52565267
@hpxml_object.clothes_washers.delete(self)
52575268
end
52585269

52595270
def check_for_errors
52605271
errors = []
52615272
begin; water_heating_system; rescue StandardError => e; errors << e.message; end
5273+
begin; hot_water_distribution; rescue StandardError => e; errors << e.message; end
52625274
return errors
52635275
end
52645276

@@ -5275,6 +5287,9 @@ def to_oga(doc)
52755287
if not @water_heating_system_idref.nil?
52765288
attached_water_heater = XMLHelper.add_element(clothes_washer, 'AttachedToWaterHeatingSystem')
52775289
XMLHelper.add_attribute(attached_water_heater, 'idref', @water_heating_system_idref)
5290+
elsif not @hot_water_distribution_idref.nil?
5291+
attached_hot_water_dist = XMLHelper.add_element(clothes_washer, 'AttachedToHotWaterDistribution')
5292+
XMLHelper.add_attribute(attached_hot_water_dist, 'idref', @hot_water_distribution_idref)
52785293
end
52795294
XMLHelper.add_element(clothes_washer, 'Location', @location, :string, @location_isdefaulted) unless @location.nil?
52805295
XMLHelper.add_element(clothes_washer, 'ModifiedEnergyFactor', @modified_energy_factor, :float) unless @modified_energy_factor.nil?
@@ -5299,6 +5314,7 @@ def from_oga(clothes_washer)
52995314
@is_shared_appliance = XMLHelper.get_value(clothes_washer, 'IsSharedAppliance', :boolean)
53005315
@number_of_units_served = XMLHelper.get_value(clothes_washer, 'NumberofUnitsServed', :integer)
53015316
@water_heating_system_idref = HPXML::get_idref(XMLHelper.get_element(clothes_washer, 'AttachedToWaterHeatingSystem'))
5317+
@hot_water_distribution_idref = HPXML::get_idref(XMLHelper.get_element(clothes_washer, 'AttachedToHotWaterDistribution'))
53025318
@location = XMLHelper.get_value(clothes_washer, 'Location', :string)
53035319
@modified_energy_factor = XMLHelper.get_value(clothes_washer, 'ModifiedEnergyFactor', :float)
53045320
@integrated_modified_energy_factor = XMLHelper.get_value(clothes_washer, 'IntegratedModifiedEnergyFactor', :float)
@@ -5405,9 +5421,9 @@ def from_oga(hpxml)
54055421

54065422
class Dishwasher < BaseElement
54075423
ATTRS = [:id, :location, :energy_factor, :rated_annual_kwh, :place_setting_capacity,
5408-
:label_electric_rate, :label_gas_rate, :label_annual_gas_cost,
5409-
:label_usage, :usage_multiplier, :is_shared_appliance, :water_heating_system_idref,
5410-
:weekday_fractions, :weekend_fractions, :monthly_multipliers]
5424+
:label_electric_rate, :label_gas_rate, :label_annual_gas_cost, :label_usage,
5425+
:usage_multiplier, :is_shared_appliance, :water_heating_system_idref,
5426+
:hot_water_distribution_idref, :weekday_fractions, :weekend_fractions, :monthly_multipliers]
54115427
attr_accessor(*ATTRS)
54125428

54135429
def water_heating_system
@@ -5421,13 +5437,25 @@ def water_heating_system
54215437
fail "Attached water heating system '#{@water_heating_system_idref}' not found for dishwasher '#{@id}'."
54225438
end
54235439

5440+
def hot_water_distribution
5441+
return if @hot_water_distribution_idref.nil?
5442+
5443+
@hpxml_object.hot_water_distributions.each do |hot_water_distribution|
5444+
next unless hot_water_distribution.id == @hot_water_distribution_idref
5445+
5446+
return hot_water_distribution
5447+
end
5448+
fail "Attached hot water distribution '#{@hot_water_distribution_idref}' not found for dishwasher '#{@id}'."
5449+
end
5450+
54245451
def delete
54255452
@hpxml_object.dishwashers.delete(self)
54265453
end
54275454

54285455
def check_for_errors
54295456
errors = []
54305457
begin; water_heating_system; rescue StandardError => e; errors << e.message; end
5458+
begin; hot_water_distribution; rescue StandardError => e; errors << e.message; end
54315459
return errors
54325460
end
54335461

@@ -5442,6 +5470,9 @@ def to_oga(doc)
54425470
if not @water_heating_system_idref.nil?
54435471
attached_water_heater = XMLHelper.add_element(dishwasher, 'AttachedToWaterHeatingSystem')
54445472
XMLHelper.add_attribute(attached_water_heater, 'idref', @water_heating_system_idref)
5473+
elsif not @hot_water_distribution_idref.nil?
5474+
attached_hot_water_dist = XMLHelper.add_element(dishwasher, 'AttachedToHotWaterDistribution')
5475+
XMLHelper.add_attribute(attached_hot_water_dist, 'idref', @hot_water_distribution_idref)
54455476
end
54465477
XMLHelper.add_element(dishwasher, 'Location', @location, :string, @location_isdefaulted) unless @location.nil?
54475478
XMLHelper.add_element(dishwasher, 'RatedAnnualkWh', @rated_annual_kwh, :float, @rated_annual_kwh_isdefaulted) unless @rated_annual_kwh.nil?
@@ -5463,6 +5494,7 @@ def from_oga(dishwasher)
54635494
@id = HPXML::get_id(dishwasher)
54645495
@is_shared_appliance = XMLHelper.get_value(dishwasher, 'IsSharedAppliance', :boolean)
54655496
@water_heating_system_idref = HPXML::get_idref(XMLHelper.get_element(dishwasher, 'AttachedToWaterHeatingSystem'))
5497+
@hot_water_distribution_idref = HPXML::get_idref(XMLHelper.get_element(dishwasher, 'AttachedToHotWaterDistribution'))
54665498
@location = XMLHelper.get_value(dishwasher, 'Location', :string)
54675499
@rated_annual_kwh = XMLHelper.get_value(dishwasher, 'RatedAnnualkWh', :float)
54685500
@energy_factor = XMLHelper.get_value(dishwasher, 'EnergyFactor', :float)

HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,7 +1786,7 @@
17861786
<sch:title>[ClothesWasherType=Shared]</sch:title>
17871787
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Appliances/h:ClothesWasher[h:IsSharedAppliance="true"]'>
17881788
<sch:assert role='ERROR' test='count(../../h:BuildingSummary/h:BuildingConstruction[h:ResidentialFacilityType[text()="single-family attached" or text()="apartment unit"]]) = 1'>Expected 1 element(s) for xpath: ../../BuildingSummary/BuildingConstruction[ResidentialFacilityType[text()="single-family attached" or text()="apartment unit"]]</sch:assert>
1789-
<sch:assert role='ERROR' test='count(h:AttachedToWaterHeatingSystem) = 1'>Expected 1 element(s) for xpath: AttachedToWaterHeatingSystem</sch:assert>
1789+
<sch:assert role='ERROR' test='count(h:AttachedToWaterHeatingSystem) + count(h:AttachedToHotWaterDistribution) = 1'>Expected 1 element(s) for xpath: AttachedToWaterHeatingSystem | AttachedToHotWaterDistribution</sch:assert>
17901790
</sch:rule>
17911791
</sch:pattern>
17921792

@@ -1851,7 +1851,7 @@
18511851
<sch:title>[DishwasherType=Shared]</sch:title>
18521852
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Appliances/h:Dishwasher[h:IsSharedAppliance="true"]'>
18531853
<sch:assert role='ERROR' test='count(../../h:BuildingSummary/h:BuildingConstruction[h:ResidentialFacilityType[text()="single-family attached" or text()="apartment unit"]]) = 1'>Expected 1 element(s) for xpath: ../../BuildingSummary/BuildingConstruction[ResidentialFacilityType[text()="single-family attached" or text()="apartment unit"]]</sch:assert>
1854-
<sch:assert role='ERROR' test='count(h:AttachedToWaterHeatingSystem) = 1'>Expected 1 element(s) for xpath: AttachedToWaterHeatingSystem</sch:assert>
1854+
<sch:assert role='ERROR' test='count(h:AttachedToWaterHeatingSystem) + count(h:AttachedToHotWaterDistribution) = 1'>Expected 1 element(s) for xpath: AttachedToWaterHeatingSystem | AttachedToHotWaterDistribution</sch:assert>
18551855
</sch:rule>
18561856
</sch:pattern>
18571857

HPXMLtoOpenStudio/tests/test_validation.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,9 @@ def test_measure_error_messages
741741
'unattached-hvac-distribution' => ["Attached HVAC distribution system 'foobar' not found for HVAC system 'HeatingSystem1'."],
742742
'unattached-skylight' => ["Attached roof 'foobar' not found for skylight 'Skylight1'."],
743743
'unattached-solar-thermal-system' => ["Attached water heating system 'foobar' not found for solar thermal system 'SolarThermalSystem1'."],
744+
'unattached-shared-clothes-washer-dhw-distribution' => ["Attached hot water distribution 'foobar' not found for clothes washer"],
744745
'unattached-shared-clothes-washer-water-heater' => ["Attached water heating system 'foobar' not found for clothes washer"],
746+
'unattached-shared-dishwasher-dhw-distribution' => ["Attached hot water distribution 'foobar' not found for dishwasher"],
745747
'unattached-shared-dishwasher-water-heater' => ["Attached water heating system 'foobar' not found for dishwasher"],
746748
'unattached-window' => ["Attached wall 'foobar' not found for window 'Window1'."] }
747749

@@ -1024,9 +1026,17 @@ def test_measure_error_messages
10241026
elsif ['unattached-solar-thermal-system'].include? error_case
10251027
hpxml = HPXML.new(hpxml_path: File.join(@sample_files_path, 'base-dhw-solar-indirect-flat-plate.xml'))
10261028
hpxml.solar_thermal_systems[0].water_heating_system_idref = 'foobar'
1029+
elsif ['unattached-shared-clothes-washer-dhw-distribution'].include? error_case
1030+
hpxml = HPXML.new(hpxml_path: File.join(@sample_files_path, 'base-bldgtype-multifamily-shared-laundry-room.xml'))
1031+
hpxml.clothes_washers[0].water_heating_system_idref = nil
1032+
hpxml.clothes_washers[0].hot_water_distribution_idref = 'foobar'
10271033
elsif ['unattached-shared-clothes-washer-water-heater'].include? error_case
10281034
hpxml = HPXML.new(hpxml_path: File.join(@sample_files_path, 'base-bldgtype-multifamily-shared-laundry-room.xml'))
10291035
hpxml.clothes_washers[0].water_heating_system_idref = 'foobar'
1036+
elsif ['unattached-shared-dishwasher-dhw-distribution'].include? error_case
1037+
hpxml = HPXML.new(hpxml_path: File.join(@sample_files_path, 'base-bldgtype-multifamily-shared-laundry-room.xml'))
1038+
hpxml.dishwashers[0].water_heating_system_idref = nil
1039+
hpxml.dishwashers[0].hot_water_distribution_idref = 'foobar'
10301040
elsif ['unattached-shared-dishwasher-water-heater'].include? error_case
10311041
hpxml = HPXML.new(hpxml_path: File.join(@sample_files_path, 'base-bldgtype-multifamily-shared-laundry-room.xml'))
10321042
hpxml.dishwashers[0].water_heating_system_idref = 'foobar'

0 commit comments

Comments
 (0)