Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BuildResidentialHPXML: create multiple Building elements #1452

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions BuildResidentialHPXML/measure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg.setDescription('Absolute/relative path of the HPXML file.')
args << arg

arg = OpenStudio::Measure::OSArgument.makeStringArgument('hpxml_path_in', false)
arg.setDisplayName('HPXML File Path In')
arg.setDescription('Absolute/relative path of the existing HPXML file.')
args << arg

arg = OpenStudio::Measure::OSArgument.makeStringArgument('software_info_program_used', false)
arg.setDisplayName('Software Info: Program Used')
arg.setDescription('The name of the software program used.')
Expand Down Expand Up @@ -3151,7 +3156,15 @@ def run(model, runner, user_arguments)
hpxml_path = File.expand_path(hpxml_path)
end

hpxml_doc = HPXMLFile.create(runner, model, args, epw_path, hpxml_path)
# Existing HPXML File
if args[:hpxml_path_in].is_initialized
hpxml_path_in = args[:hpxml_path_in].get
unless (Pathname.new hpxml_path_in).absolute?
hpxml_path_in = File.expand_path(hpxml_path_in)
end
end

hpxml_doc = HPXMLFile.create(runner, model, args, epw_path, hpxml_path, hpxml_path_in)
if not hpxml_doc
runner.registerError('Unsuccessful creation of HPXML file.')
return false
Expand Down Expand Up @@ -3357,7 +3370,7 @@ def argument_errors(args)
end

class HPXMLFile
def self.create(runner, model, args, epw_path, hpxml_path)
def self.create(runner, model, args, epw_path, hpxml_path, hpxml_path_in)
epw_file = OpenStudio::EpwFile.new(epw_path)
if (args[:hvac_control_heating_season_period].to_s == HPXML::BuildingAmerica) || (args[:hvac_control_cooling_season_period].to_s == HPXML::BuildingAmerica) || (args[:apply_defaults])
weather = WeatherProcess.new(epw_path: epw_path, runner: nil)
Expand Down Expand Up @@ -3428,6 +3441,7 @@ def self.create(runner, model, args, epw_path, hpxml_path)
renumber_hpxml_ids(hpxml)

hpxml_doc = hpxml.to_oga()
hpxml_doc = add_building(hpxml_path_in, hpxml_doc)
XMLHelper.write_file(hpxml_doc, hpxml_path)

if args[:apply_validation]
Expand All @@ -3441,11 +3455,39 @@ def self.create(runner, model, args, epw_path, hpxml_path)
eri_version = Constants.ERIVersions[-1]
HPXMLDefaults.apply(runner, hpxml, eri_version, weather, epw_file: epw_file)
hpxml_doc = hpxml.to_oga()
hpxml_doc = add_building(hpxml_path_in, hpxml_doc)
end

return hpxml_doc
end

def self.add_building(hpxml_path_in, hpxml_doc)
return hpxml_doc if hpxml_path_in.nil?

hpxml_doc_in = XMLHelper.parse_file(hpxml_path_in)
hpxml_in = XMLHelper.get_element(hpxml_doc_in, '/HPXML')
building_id = "#{XMLHelper.get_elements(hpxml_in, 'Building').size + 1}"

hpxml_element = XMLHelper.get_element(hpxml_doc, '/HPXML')
building_element = XMLHelper.get_element(hpxml_element, 'Building')
new_building_element = Marshal.load(Marshal.dump(building_element)) # Deep copy

# Make all IDs unique so the HPXML is valid
new_building_element.each_node do |node|
next unless node.is_a?(Oga::XML::Element)

if not XMLHelper.get_attribute_value(node, 'id').nil?
XMLHelper.add_attribute(node, 'id', "#{XMLHelper.get_attribute_value(node, 'id')}_#{building_id}")
elsif not XMLHelper.get_attribute_value(node, 'idref').nil?
XMLHelper.add_attribute(node, 'idref', "#{XMLHelper.get_attribute_value(node, 'idref')}_#{building_id}")
end
end

hpxml_in.children << new_building_element

return hpxml_doc_in
end

def self.validate_hpxml(runner, hpxml, hpxml_doc, hpxml_path)
# Check for errors in the HPXML object
errors = hpxml.check_for_errors()
Expand Down
14 changes: 11 additions & 3 deletions BuildResidentialHPXML/measure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<schema_version>3.1</schema_version>
<name>build_residential_hpxml</name>
<uid>a13a8983-2b01-4930-8af2-42030b6e4233</uid>
<version_id>1fcda896-05c3-49a8-93d6-3d49c15fa301</version_id>
<version_modified>2023-07-26T21:30:02Z</version_modified>
<version_id>4461d314-53c5-4d5f-bf26-80497817e1d2</version_id>
<version_modified>2023-07-28T18:26:12Z</version_modified>
<xml_checksum>2C38F48B</xml_checksum>
<class_name>BuildResidentialHPXML</class_name>
<display_name>HPXML Builder</display_name>
Expand All @@ -19,6 +19,14 @@
<required>true</required>
<model_dependent>false</model_dependent>
</argument>
<argument>
<name>hpxml_path_in</name>
<display_name>HPXML File Path In</display_name>
<description>Absolute/relative path of the existing HPXML file.</description>
<type>String</type>
<required>false</required>
<model_dependent>false</model_dependent>
</argument>
<argument>
<name>software_info_program_used</name>
<display_name>Software Info: Program Used</display_name>
Expand Down Expand Up @@ -6691,7 +6699,7 @@
<filename>measure.rb</filename>
<filetype>rb</filetype>
<usage_type>script</usage_type>
<checksum>DA29841B</checksum>
<checksum>7EE00D9E</checksum>
</file>
<file>
<filename>geometry.rb</filename>
Expand Down
56 changes: 29 additions & 27 deletions tasks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,37 +76,39 @@ def create_hpxmls
exit!
end

hpxml = HPXML.new(hpxml_path: hpxml_path)
if hpxml_path.include? 'ASHRAE_Standard_140'
apply_hpxml_modification_ashrae_140(hpxml)
else
apply_hpxml_modification(File.basename(hpxml_path), hpxml)
end
hpxml_doc = hpxml.to_oga()

if hpxml_path.include? 'base-multiple-buildings.xml'
# HPXML class doesn't support multiple buildings, so we'll stitch together manually.
hpxml_element = XMLHelper.get_element(hpxml_doc, '/HPXML')
building_element = XMLHelper.get_element(hpxml_element, 'Building')
for i in 2..3
new_building_element = Marshal.load(Marshal.dump(building_element)) # Deep copy

# Make all IDs unique so the HPXML is valid
new_building_element.each_node do |node|
next unless node.is_a?(Oga::XML::Element)

if not XMLHelper.get_attribute_value(node, 'id').nil?
XMLHelper.add_attribute(node, 'id', "#{XMLHelper.get_attribute_value(node, 'id')}_#{i}")
elsif not XMLHelper.get_attribute_value(node, 'idref').nil?
XMLHelper.add_attribute(node, 'idref', "#{XMLHelper.get_attribute_value(node, 'idref')}_#{i}")
if not hpxml_path.include? 'base-multiple-buildings.xml'
hpxml = HPXML.new(hpxml_path: hpxml_path)
if hpxml_path.include? 'ASHRAE_Standard_140'
apply_hpxml_modification_ashrae_140(hpxml)
else
apply_hpxml_modification(File.basename(hpxml_path), hpxml)
end
hpxml_doc = hpxml.to_oga()

if hpxml_path.include? 'base-multiple-buildings.xml'
# HPXML class doesn't support multiple buildings, so we'll stitch together manually.
hpxml_element = XMLHelper.get_element(hpxml_doc, '/HPXML')
building_element = XMLHelper.get_element(hpxml_element, 'Building')
for i in 2..3
new_building_element = Marshal.load(Marshal.dump(building_element)) # Deep copy

# Make all IDs unique so the HPXML is valid
new_building_element.each_node do |node|
next unless node.is_a?(Oga::XML::Element)

if not XMLHelper.get_attribute_value(node, 'id').nil?
XMLHelper.add_attribute(node, 'id', "#{XMLHelper.get_attribute_value(node, 'id')}_#{i}")
elsif not XMLHelper.get_attribute_value(node, 'idref').nil?
XMLHelper.add_attribute(node, 'idref', "#{XMLHelper.get_attribute_value(node, 'idref')}_#{i}")
end
end
end

hpxml_element.children << new_building_element
hpxml_element.children << new_building_element
end
end
end

XMLHelper.write_file(hpxml_doc, hpxml_path)
XMLHelper.write_file(hpxml_doc, hpxml_path)
end

errors, _warnings = XMLValidator.validate_against_schema(hpxml_path, schema_validator)
next unless errors.size > 0
Expand Down
2 changes: 1 addition & 1 deletion workflow/hpxml_inputs.json
Original file line number Diff line number Diff line change
Expand Up @@ -3189,7 +3189,7 @@
},
"sample_files/base-multiple-buildings.xml": {
"parent_hpxml": "sample_files/base.xml",
"clothes_dryer_present": false
"hpxml_path_in": "workflow/sample_files/base.xml"
},
"sample_files/base-pv.xml": {
"parent_hpxml": "sample_files/base.xml",
Expand Down
Loading