Skip to content

Commit 1a12948

Browse files
authored
Merge pull request #1177 from NREL/multiple_climate_zones
Support multiple IECC climate zones in HPXML class
2 parents d0460db + 3a4cc9e commit 1a12948

9 files changed

Lines changed: 105 additions & 71 deletions

File tree

BuildResidentialHPXML/measure.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3831,8 +3831,8 @@ def self.set_climate_and_risk_zones(hpxml, args)
38313831
hpxml.climate_and_risk_zones.weather_station_id = 'WeatherStation'
38323832

38333833
if args[:site_iecc_zone].is_initialized
3834-
hpxml.climate_and_risk_zones.iecc_zone = args[:site_iecc_zone].get
3835-
hpxml.climate_and_risk_zones.iecc_year = 2006
3834+
hpxml.climate_and_risk_zones.climate_zone_ieccs.add(zone: args[:site_iecc_zone].get,
3835+
year: 2006)
38363836
end
38373837

38383838
weather_station_name = File.basename(args[:weather_station_epw_filepath]).gsub('.epw', '')

BuildResidentialHPXML/measure.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
<schema_version>3.0</schema_version>
44
<name>build_residential_hpxml</name>
55
<uid>a13a8983-2b01-4930-8af2-42030b6e4233</uid>
6-
<version_id>adadab12-4481-4c1f-bb0f-980c6dbdf441</version_id>
7-
<version_modified>20220818T192810Z</version_modified>
6+
<version_id>03a79ea8-0073-4958-a3bb-423259bbcdf9</version_id>
7+
<version_modified>20220915T153454Z</version_modified>
88
<xml_checksum>2C38F48B</xml_checksum>
99
<class_name>BuildResidentialHPXML</class_name>
1010
<display_name>HPXML Builder</display_name>
@@ -6404,7 +6404,7 @@
64046404
<filename>measure.rb</filename>
64056405
<filetype>rb</filetype>
64066406
<usage_type>script</usage_type>
6407-
<checksum>788EEDBC</checksum>
6407+
<checksum>522E2920</checksum>
64086408
</file>
64096409
</files>
64106410
</measure>

HPXMLtoOpenStudio/measure.xml

Lines changed: 26 additions & 26 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>22a4382c-e1f6-4fe6-aa03-b7e47e4194e1</version_id>
7-
<version_modified>20220912T230453Z</version_modified>
6+
<version_id>700496d3-089d-489d-a2cc-ad09d7869d03</version_id>
7+
<version_modified>20220915T180012Z</version_modified>
88
<xml_checksum>D8922A73</xml_checksum>
99
<class_name>HPXMLtoOpenStudio</class_name>
1010
<display_name>HPXML to OpenStudio Translator</display_name>
@@ -439,12 +439,6 @@
439439
<usage_type>resource</usage_type>
440440
<checksum>DF9CC863</checksum>
441441
</file>
442-
<file>
443-
<filename>test_validation.rb</filename>
444-
<filetype>rb</filetype>
445-
<usage_type>test</usage_type>
446-
<checksum>2302726B</checksum>
447-
</file>
448442
<file>
449443
<filename>test_pv.rb</filename>
450444
<filetype>rb</filetype>
@@ -547,24 +541,12 @@
547541
<usage_type>resource</usage_type>
548542
<checksum>B6BC6A9D</checksum>
549543
</file>
550-
<file>
551-
<filename>hpxml.rb</filename>
552-
<filetype>rb</filetype>
553-
<usage_type>resource</usage_type>
554-
<checksum>D6374C8B</checksum>
555-
</file>
556544
<file>
557545
<filename>test_airflow.rb</filename>
558546
<filetype>rb</filetype>
559547
<usage_type>test</usage_type>
560548
<checksum>15015829</checksum>
561549
</file>
562-
<file>
563-
<filename>test_defaults.rb</filename>
564-
<filetype>rb</filetype>
565-
<usage_type>test</usage_type>
566-
<checksum>C6A2AF80</checksum>
567-
</file>
568550
<file>
569551
<filename>weather.rb</filename>
570552
<filetype>rb</filetype>
@@ -577,12 +559,6 @@
577559
<usage_type>resource</usage_type>
578560
<checksum>A2B7F8E1</checksum>
579561
</file>
580-
<file>
581-
<filename>hpxml_defaults.rb</filename>
582-
<filetype>rb</filetype>
583-
<usage_type>resource</usage_type>
584-
<checksum>5694E794</checksum>
585-
</file>
586562
<file>
587563
<version>
588564
<software_program>OpenStudio</software_program>
@@ -594,5 +570,29 @@
594570
<usage_type>script</usage_type>
595571
<checksum>4F98F3F7</checksum>
596572
</file>
573+
<file>
574+
<filename>hpxml.rb</filename>
575+
<filetype>rb</filetype>
576+
<usage_type>resource</usage_type>
577+
<checksum>0D60DE1E</checksum>
578+
</file>
579+
<file>
580+
<filename>test_defaults.rb</filename>
581+
<filetype>rb</filetype>
582+
<usage_type>test</usage_type>
583+
<checksum>7950A1A2</checksum>
584+
</file>
585+
<file>
586+
<filename>hpxml_defaults.rb</filename>
587+
<filetype>rb</filetype>
588+
<usage_type>resource</usage_type>
589+
<checksum>6ED20DA1</checksum>
590+
</file>
591+
<file>
592+
<filename>test_validation.rb</filename>
593+
<filetype>rb</filetype>
594+
<usage_type>test</usage_type>
595+
<checksum>84BC4702</checksum>
596+
</file>
597597
</files>
598598
</measure>

HPXMLtoOpenStudio/resources/hpxml.rb

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,7 +1106,7 @@ class EmissionsScenario < BaseElement
11061106
attr_accessor(*ATTRS)
11071107

11081108
def delete
1109-
@hpxml_object.emissions_scenarios.delete(self)
1109+
@hpxml_object.header.emissions_scenarios.delete(self)
11101110
end
11111111

11121112
def check_for_errors
@@ -1203,7 +1203,7 @@ class UtilityBillScenario < BaseElement
12031203
attr_accessor(*ATTRS)
12041204

12051205
def delete
1206-
@hpxml_object.utility_bill_scenarios.delete(self)
1206+
@hpxml_object.header.utility_bill_scenarios.delete(self)
12071207
end
12081208

12091209
def check_for_errors
@@ -1459,12 +1459,17 @@ def from_oga(hpxml)
14591459
end
14601460

14611461
class ClimateandRiskZones < BaseElement
1462-
ATTRS = [:iecc_year, :iecc_zone, :weather_station_id, :weather_station_name, :weather_station_wmo,
1463-
:weather_station_epw_filepath]
1462+
def initialize(hpxml_object, *args)
1463+
@climate_zone_ieccs = ClimateZoneIECCs.new(hpxml_object)
1464+
super(hpxml_object, *args)
1465+
end
1466+
ATTRS = [:weather_station_id, :weather_station_name, :weather_station_wmo, :weather_station_epw_filepath]
14641467
attr_accessor(*ATTRS)
1468+
attr_reader(:climate_zone_ieccs)
14651469

14661470
def check_for_errors
14671471
errors = []
1472+
errors += @climate_zone_ieccs.check_for_errors
14681473
return errors
14691474
end
14701475

@@ -1473,11 +1478,7 @@ def to_oga(doc)
14731478

14741479
climate_and_risk_zones = XMLHelper.create_elements_as_needed(doc, ['HPXML', 'Building', 'BuildingDetails', 'ClimateandRiskZones'])
14751480

1476-
if (not @iecc_year.nil?) && (not @iecc_zone.nil?)
1477-
climate_zone_iecc = XMLHelper.add_element(climate_and_risk_zones, 'ClimateZoneIECC')
1478-
XMLHelper.add_element(climate_zone_iecc, 'Year', @iecc_year, :integer, @iecc_year_isdefaulted) unless @iecc_year.nil?
1479-
XMLHelper.add_element(climate_zone_iecc, 'ClimateZone', @iecc_zone, :string, @iecc_zone_isdefaulted) unless @iecc_zone.nil?
1480-
end
1481+
@climate_zone_ieccs.to_oga(climate_and_risk_zones)
14811482

14821483
if not @weather_station_id.nil?
14831484
weather_station = XMLHelper.add_element(climate_and_risk_zones, 'WeatherStation')
@@ -1495,8 +1496,8 @@ def from_oga(hpxml)
14951496
climate_and_risk_zones = XMLHelper.get_element(hpxml, 'Building/BuildingDetails/ClimateandRiskZones')
14961497
return if climate_and_risk_zones.nil?
14971498

1498-
@iecc_year = XMLHelper.get_value(climate_and_risk_zones, 'ClimateZoneIECC/Year', :integer)
1499-
@iecc_zone = XMLHelper.get_value(climate_and_risk_zones, 'ClimateZoneIECC/ClimateZone', :string)
1499+
@climate_zone_ieccs.from_oga(climate_and_risk_zones)
1500+
15001501
weather_station = XMLHelper.get_element(climate_and_risk_zones, 'WeatherStation')
15011502
if not weather_station.nil?
15021503
@weather_station_id = HPXML::get_id(weather_station)
@@ -1507,6 +1508,47 @@ def from_oga(hpxml)
15071508
end
15081509
end
15091510

1511+
class ClimateZoneIECCs < BaseArrayElement
1512+
def add(**kwargs)
1513+
self << ClimateZoneIECC.new(@hpxml_object, **kwargs)
1514+
end
1515+
1516+
def from_oga(climate_and_risk_zones)
1517+
return if climate_and_risk_zones.nil?
1518+
1519+
XMLHelper.get_elements(climate_and_risk_zones, 'ClimateZoneIECC').each do |climate_zone_iecc|
1520+
self << ClimateZoneIECC.new(@hpxml_object, climate_zone_iecc)
1521+
end
1522+
end
1523+
end
1524+
1525+
class ClimateZoneIECC < BaseElement
1526+
ATTRS = [:year, :zone]
1527+
attr_accessor(*ATTRS)
1528+
1529+
def delete
1530+
@hpxml_object.climate_and_risk_zones.climate_zone_ieccs.delete(self)
1531+
end
1532+
1533+
def check_for_errors
1534+
errors = []
1535+
return errors
1536+
end
1537+
1538+
def to_oga(climate_and_risk_zones)
1539+
climate_zone_iecc = XMLHelper.add_element(climate_and_risk_zones, 'ClimateZoneIECC')
1540+
XMLHelper.add_element(climate_zone_iecc, 'Year', @year, :integer, @year_isdefaulted) unless @year.nil?
1541+
XMLHelper.add_element(climate_zone_iecc, 'ClimateZone', @zone, :string, @zone_isdefaulted) unless @zone.nil?
1542+
end
1543+
1544+
def from_oga(climate_zone_iecc)
1545+
return if climate_zone_iecc.nil?
1546+
1547+
@year = XMLHelper.get_value(climate_zone_iecc, 'Year', :integer)
1548+
@zone = XMLHelper.get_value(climate_zone_iecc, 'ClimateZone', :string)
1549+
end
1550+
end
1551+
15101552
class AirInfiltrationMeasurements < BaseArrayElement
15111553
def add(**kwargs)
15121554
self << AirInfiltrationMeasurement.new(@hpxml_object, **kwargs)

HPXMLtoOpenStudio/resources/hpxml_defaults.rb

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -494,18 +494,13 @@ def self.apply_building_construction(hpxml, cfa, nbeds, infil_volume)
494494
end
495495

496496
def self.apply_climate_and_risk_zones(hpxml, epw_file)
497-
if (not epw_file.nil?) && (hpxml.climate_and_risk_zones.iecc_zone.nil? || hpxml.climate_and_risk_zones.iecc_year.nil?)
498-
if hpxml.climate_and_risk_zones.iecc_zone.nil?
499-
climate_zone_iecc = Location.get_climate_zone_iecc(epw_file.wmoNumber)
500-
if Constants.IECCZones.include? climate_zone_iecc
501-
hpxml.climate_and_risk_zones.iecc_zone = climate_zone_iecc
502-
hpxml.climate_and_risk_zones.iecc_zone_isdefaulted = true
503-
end
504-
end
505-
506-
if (not hpxml.climate_and_risk_zones.iecc_zone.nil?) && hpxml.climate_and_risk_zones.iecc_year.nil?
507-
hpxml.climate_and_risk_zones.iecc_year = 2006
508-
hpxml.climate_and_risk_zones.iecc_year_isdefaulted = true
497+
if (not epw_file.nil?) && hpxml.climate_and_risk_zones.climate_zone_ieccs.empty?
498+
zone = Location.get_climate_zone_iecc(epw_file.wmoNumber)
499+
if not zone.nil?
500+
hpxml.climate_and_risk_zones.climate_zone_ieccs.add(zone: zone,
501+
year: 2006,
502+
zone_isdefaulted: true,
503+
year_isdefaulted: true)
509504
end
510505
end
511506
end
@@ -1701,7 +1696,7 @@ def self.apply_water_heaters(hpxml, nbeds, eri_version, schedules_file)
17011696
end
17021697
end
17031698
if water_heating_system.location.nil?
1704-
water_heating_system.location = Waterheater.get_default_location(hpxml, hpxml.climate_and_risk_zones.iecc_zone)
1699+
water_heating_system.location = Waterheater.get_default_location(hpxml, hpxml.climate_and_risk_zones.climate_zone_ieccs[0].zone)
17051700
water_heating_system.location_isdefaulted = true
17061701
end
17071702
next unless water_heating_system.usage_bin.nil? && (not water_heating_system.uniform_energy_factor.nil?) # FHR & UsageBin only applies to UEF

HPXMLtoOpenStudio/tests/test_defaults.rb

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -389,23 +389,20 @@ def test_building_construction
389389
def test_climate_and_risk_zones
390390
# Test inputs not overridden by defaults
391391
hpxml = _create_hpxml('base.xml')
392-
hpxml.climate_and_risk_zones.iecc_year = 2009
393-
hpxml.climate_and_risk_zones.iecc_zone = '2B'
392+
hpxml.climate_and_risk_zones.climate_zone_ieccs[0].year = 2009
393+
hpxml.climate_and_risk_zones.climate_zone_ieccs[0].zone = '2B'
394394
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
395395
hpxml_default = _test_measure()
396396
_test_default_climate_and_risk_zones_values(hpxml_default, 2009, '2B')
397397

398398
# Test defaults
399-
hpxml.climate_and_risk_zones.iecc_year = nil
400-
hpxml.climate_and_risk_zones.iecc_zone = nil
399+
hpxml.climate_and_risk_zones.climate_zone_ieccs[0].delete
401400
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
402401
hpxml_default = _test_measure()
403402
_test_default_climate_and_risk_zones_values(hpxml_default, 2006, '5B')
404403

405404
# Test defaults - invalid IECC zone
406405
hpxml = _create_hpxml('base-location-capetown-zaf.xml')
407-
hpxml.climate_and_risk_zones.iecc_year = nil
408-
hpxml.climate_and_risk_zones.iecc_zone = nil
409406
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
410407
hpxml_default = _test_measure()
411408
_test_default_climate_and_risk_zones_values(hpxml_default, nil, nil)
@@ -3470,14 +3467,14 @@ def _test_default_occupancy_values(hpxml, num_occupants, weekday_sch, weekend_sc
34703467

34713468
def _test_default_climate_and_risk_zones_values(hpxml, iecc_year, iecc_zone)
34723469
if iecc_year.nil?
3473-
assert_nil(hpxml.climate_and_risk_zones.iecc_year)
3470+
assert_equal(0, hpxml.climate_and_risk_zones.climate_zone_ieccs.size)
34743471
else
3475-
assert_equal(iecc_year, hpxml.climate_and_risk_zones.iecc_year)
3472+
assert_equal(iecc_year, hpxml.climate_and_risk_zones.climate_zone_ieccs[0].year)
34763473
end
34773474
if iecc_zone.nil?
3478-
assert_nil(hpxml.climate_and_risk_zones.iecc_zone)
3475+
assert_equal(0, hpxml.climate_and_risk_zones.climate_zone_ieccs.size)
34793476
else
3480-
assert_equal(iecc_zone, hpxml.climate_and_risk_zones.iecc_zone)
3477+
assert_equal(iecc_zone, hpxml.climate_and_risk_zones.climate_zone_ieccs[0].zone)
34813478
end
34823479
end
34833480

HPXMLtoOpenStudio/tests/test_validation.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ def test_schematron_error_messages
398398
hpxml = HPXML.new(hpxml_path: File.join(@sample_files_path, 'base.xml'))
399399
hpxml.header.transaction = 'modify'
400400
hpxml.site.site_type = 'mountain'
401-
hpxml.climate_and_risk_zones.iecc_year = 2020
401+
hpxml.climate_and_risk_zones.climate_zone_ieccs[0].year = 2020
402402
hpxml.roofs.each do |roof|
403403
roof.radiant_barrier_grade = 4
404404
end

docs/source/workflow_inputs.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -530,19 +530,19 @@ HPXML Climate Zones
530530
HPXML Climate Zone IECC
531531
***********************
532532

533-
Climate zone information can be entered as an ``/HPXML/Building/BuildingDetails/ClimateandRiskZones/ClimateZoneIECC``.
533+
Climate zone information can be optionally entered as an ``/HPXML/Building/BuildingDetails/ClimateandRiskZones/ClimateZoneIECC``.
534534

535535
================================= ======== ===== =========== ======== ======== ===============
536536
Element Type Units Constraints Required Default Description
537537
================================= ======== ===== =========== ======== ======== ===============
538-
``Year`` integer See [#]_ No 2006 IECC year
539-
``ClimateZone`` string See [#]_ No See [#]_ IECC zone
538+
``Year`` integer See [#]_ Yes IECC year
539+
``ClimateZone`` string See [#]_ Yes IECC zone
540540
================================= ======== ===== =========== ======== ======== ===============
541541

542542
.. [#] Year choices are 2003, 2006, 2009, 2012, 2015, 2018, or 2021.
543543
.. [#] ClimateZone choices are "1A", "1B", "1C", "2A", "2B", "2C", "3A", "3B", "3C", "4A", "4B", "4C", "5A", "5B", "5C", "6A", "6B", "6C", "7", or "8".
544-
.. [#] If ClimateZone not provided, defaults according to the EPW weather file header.
545544
545+
If Climate zone information not provided, defaults according to the EPW weather file header.
546546

547547
Weather information is entered in ``/HPXML/Building/BuildingDetails/ClimateandRiskZones/WeatherStation``.
548548

docs/source/workflow_outputs.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ So the sum of all end uses for a given fuel (e.g., sum of all "End Use: Natural
132132
End Use: Electricity: Hot Water Solar Thermal Pump (MBtu) Non-zero only when using detailed (not simple) solar thermal inputs
133133
End Use: Electricity: Lighting Interior (MBtu)
134134
End Use: Electricity: Lighting Garage (MBtu)
135-
End Use: Electricity: Lighting Exterior (MBtu)
135+
End Use: Electricity: Lighting Exterior (MBtu) Includes exterior holiday lighting
136136
End Use: Electricity: Mech Vent (MBtu) Excludes preheating/precooling
137137
End Use: Electricity: Mech Vent Preheating (MBtu)
138138
End Use: Electricity: Mech Vent Precooling (MBtu)

0 commit comments

Comments
 (0)