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

New ResStockArgumentsPostHPXML measure #929

Open
wants to merge 32 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
172879c
Rename ResstockArguments to ResStockArgumentsPreHPXML.
joseph-robertson May 13, 2022
fa408c7
Update measure name in other measures and lookup.
joseph-robertson May 13, 2022
44347c3
Stub new ResStockArgumentsPostHPXML measure.
joseph-robertson May 13, 2022
771042c
Update meta measures for new measure.
joseph-robertson May 13, 2022
2abcc64
Get meta measures working properly.
joseph-robertson May 13, 2022
1587e5b
Update measure descriptions.
joseph-robertson May 13, 2022
7bdf4da
More description updates.
joseph-robertson May 13, 2022
e111940
Merge branch 'develop' into resstock-args-refactor
joseph-robertson May 13, 2022
6fad137
Rename pre hpxml back to original.
joseph-robertson May 13, 2022
fd288ae
Revert lookup.
joseph-robertson May 13, 2022
06133ea
Merge branch 'develop' into resstock-args-refactor
joseph-robertson May 17, 2022
87e876b
Measure updates.
joseph-robertson May 17, 2022
957b9c9
Temp code in building existing model.
joseph-robertson May 17, 2022
3a5effb
Remove project folders before each test.
joseph-robertson May 17, 2022
be0e390
Squashed 'resources/hpxml-measures/' changes from c015c17d0ee..cdaa49…
joseph-robertson May 19, 2022
a8bfe43
Merge commit 'be0e390519975d5028881cfb584b5c89bef9f497' into resstock…
joseph-robertson May 19, 2022
94c5b04
Ignore new debug argument for resstock arguments.
joseph-robertson May 19, 2022
e6736f6
Merge branch 'develop' into resstock-args-refactor
joseph-robertson May 19, 2022
5c23cf2
Request setpoint output vars.
joseph-robertson May 20, 2022
53f3fc0
Latest results.
May 21, 2022
a8fc8d3
Merge branch 'develop' into resstock-args-refactor
joseph-robertson Jun 6, 2022
bfa8478
Merge branch 'develop' into resstock-args-refactor
joseph-robertson Jul 8, 2022
76ef1b6
Latest results.
Jul 8, 2022
d2d0ceb
Merge branch 'develop' into resstock-args-refactor
joseph-robertson Nov 3, 2022
55b9fa5
Clean up top level measures.
joseph-robertson Nov 3, 2022
c7c7948
Latest results.
Nov 4, 2022
4f7106d
Update changelog.
joseph-robertson Nov 4, 2022
87279c6
Update docs.
joseph-robertson Nov 4, 2022
2dac598
Revert output vars request in yml.
joseph-robertson Nov 4, 2022
ecd366d
Latest results.
Nov 4, 2022
abae054
Merge branch 'develop' into resstock-args-refactor
joseph-robertson Nov 14, 2022
b68c82f
Merge branch 'develop' into resstock-args-refactor
joseph-robertson Nov 16, 2022
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Features
- Modeled floor area based on AHS 2021 and AHS 2019 ([#978](https://github.com/NREL/resstock/pull/978))
- Add area median income ([#1004](https://github.com/NREL/resstock/pull/1004))
- Update to OpenStudio v3.5.0 ([#1006](https://github.com/NREL/resstock/pull/1006))
- Add new ResStockArgumentsPostHPXML measure to the workflow that post-processes the output of the BuildResidentialHPXML and BuildResidentialScheduleFile measures ([#929](https://github.com/NREL/resstock/pull/929))

Fixes
- Clean up option names for natural ventilation and hot water distribution ([#828](https://github.com/NREL/resstock/pull/828))
Expand Down
11 changes: 11 additions & 0 deletions docs/read_the_docs/source/tutorial/architecture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ The BuildExistingModel and ApplyUpgrade meta measures call the following model m
1 ResStockArguments Model No ResStock
2 BuildResidentialHPXML Model No OS-HPXML
3 BuildResidentialScheduleFile Model No OS-HPXML
4 ResStockArgumentsPostHPXML Model No ResStock
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the workflow makes sense. This allows for ResStock custom edits to the OS-HPXML workflow.

===== ============================= ================== ========= ============= ==========================

Model Measures
Expand Down Expand Up @@ -112,6 +113,16 @@ They contribute to the generation of the model.
:start-after: <modeler_description>
:end-before: <

**ResStockArgumentsPostHPXML**

.. include:: ../../../../measures/ResStockArgumentsPostHPXML/measure.xml
:start-after: <description>
:end-before: <

.. include:: ../../../../measures/ResStockArgumentsPostHPXML/measure.xml
:start-after: <modeler_description>
:end-before: <

.. _tutorial-apply-upgrade:

**ApplyUpgrade**
Expand Down
49 changes: 27 additions & 22 deletions measures/ApplyUpgrade/measure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ def run(model, runner, user_arguments)
end

measures['ResStockArguments'] = [{}] if !measures.keys.include?('ResStockArguments') # upgrade is via another measure
measures['ResStockArgumentsPostHPXML'] = [{}] if !measures.keys.include?('ResStockArgumentsPostHPXML') # upgrade is via another measure

# Add measure arguments from existing building if needed
parameters = get_parameters_ordered_from_options_lookup_tsv(lookup_csv_data, characteristics_dir)
Expand All @@ -306,7 +307,8 @@ def run(model, runner, user_arguments)
end

# Get the absolute paths relative to this meta measure in the run directory
if not apply_measures(measures_dir, { 'ResStockArguments' => measures['ResStockArguments'] }, new_runner, model, true, 'OpenStudio::Measure::ModelMeasure', nil)
if not apply_measures(measures_dir, { 'ResStockArguments' => measures['ResStockArguments'] }, new_runner, model, true, 'OpenStudio::Measure::ModelMeasure')
register_logs(runner, new_runner)
return false
end
end # apply_package_upgrade
Expand All @@ -322,6 +324,7 @@ def run(model, runner, user_arguments)
hpxml_path = File.expand_path('../upgraded.xml')
measures['BuildResidentialHPXML'] = [{ 'hpxml_path' => hpxml_path }]
measures['BuildResidentialScheduleFile'] = [{ 'hpxml_path' => hpxml_path, 'hpxml_output_path' => hpxml_path }]
measures['ResStockArgumentsPostHPXML'] = [{ 'hpxml_path' => hpxml_path }]

new_runner.result.stepValues.each do |step_value|
value = get_value_from_workflow_step_value(step_value)
Expand Down Expand Up @@ -374,7 +377,7 @@ def run(model, runner, user_arguments)
measures['BuildResidentialHPXML'][0]['software_info_program_used'] = 'ResStock'
measures['BuildResidentialHPXML'][0]['software_info_program_version'] = Version::ResStock_Version

# Get registered values and pass them to BuildResidentialHPXML
# Simulation control
measures['BuildResidentialHPXML'][0]['simulation_control_timestep'] = values['simulation_control_timestep']
if !values['simulation_control_run_period_begin_month'].nil? && !values['simulation_control_run_period_begin_day_of_month'].nil? && !values['simulation_control_run_period_end_month'].nil? && !values['simulation_control_run_period_end_day_of_month'].nil?
begin_month = "#{Date::ABBR_MONTHNAMES[values['simulation_control_run_period_begin_month']]}"
Expand Down Expand Up @@ -415,36 +418,38 @@ def run(model, runner, user_arguments)
measures['BuildResidentialHPXML'][0]['utility_bill_pv_monthly_grid_connection_fee_units'] = values['utility_bill_pv_monthly_grid_connection_fee_units']
measures['BuildResidentialHPXML'][0]['utility_bill_pv_monthly_grid_connection_fees'] = values['utility_bill_pv_monthly_grid_connection_fees']

# Get registered values and pass them to BuildResidentialScheduleFile
# BuildResidentialScheduleFile
measures['BuildResidentialScheduleFile'][0]['schedules_random_seed'] = values['building_id']
measures['BuildResidentialScheduleFile'][0]['output_csv_path'] = File.expand_path('../schedules.csv')

# ResStockArgumentsPostHPXML
measures['ResStockArgumentsPostHPXML'][0]['output_csv_path'] = File.expand_path('../schedules.csv')

# Specify measures to run
measures['BuildResidentialHPXML'][0]['apply_defaults'] = true
measures_to_apply_hash = { hpxml_measures_dir => { 'BuildResidentialHPXML' => measures['BuildResidentialHPXML'], 'BuildResidentialScheduleFile' => measures['BuildResidentialScheduleFile'] },
measures_dir => {} }

upgrade_measures = measures.keys - ['ResStockArguments', 'BuildResidentialHPXML', 'BuildResidentialScheduleFile']
upgrade_measures.each do |upgrade_measure|
measures_to_apply_hash[measures_dir][upgrade_measure] = measures[upgrade_measure]
if not apply_measures(hpxml_measures_dir, { 'BuildResidentialHPXML' => measures['BuildResidentialHPXML'], 'BuildResidentialScheduleFile' => measures['BuildResidentialScheduleFile'] }, new_runner, model, true, 'OpenStudio::Measure::ModelMeasure', 'upgraded.osw')
register_logs(runner, new_runner)
return false
end
measures_to_apply_hash.each_with_index do |(dir, measures_to_apply), i|
next if measures_to_apply.empty?

osw_out = 'upgraded.osw'
osw_out = "upgraded#{i + 1}.osw" if i > 0
next unless not apply_measures(dir, measures_to_apply, new_runner, model, true, 'OpenStudio::Measure::ModelMeasure', osw_out)
if not apply_measures(measures_dir, { 'ResStockArgumentsPostHPXML' => measures['ResStockArgumentsPostHPXML'] }, new_runner, model, true, 'OpenStudio::Measure::ModelMeasure')
register_logs(runner, new_runner)
return false
end

new_runner.result.warnings.each do |warning|
runner.registerWarning(warning.logMessage)
end
new_runner.result.info.each do |info|
runner.registerInfo(info.logMessage)
end
new_runner.result.errors.each do |error|
runner.registerError(error.logMessage)
# Additional upgrade measures
measures_to_apply_hash = {}
upgrade_measures = measures.keys - ['ResStockArguments', 'BuildResidentialHPXML', 'BuildResidentialScheduleFile', 'ResStockArgumentsPostHPXML']
upgrade_measures.each do |upgrade_measure|
measures_to_apply_hash[upgrade_measure] = measures[upgrade_measure]
end

if !measures_to_apply_hash.empty?
if not apply_measures(measures_dir, measures_to_apply_hash, new_runner, model, true, 'OpenStudio::Measure::ModelMeasure', 'upgraded2.osw')
register_logs(runner, new_runner)
return false
end
return false
end

# Copy upgraded.xml to home.xml for downstream HPXMLtoOpenStudio
Expand Down
6 changes: 3 additions & 3 deletions measures/ApplyUpgrade/measure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<schema_version>3.0</schema_version>
<name>apply_upgrade</name>
<uid>33f1654c-f734-43d1-b35d-9d2856e41b5a</uid>
<version_id>bbc2ca5f-4f0f-4baa-8b89-4df062c9eae1</version_id>
<version_modified>20220912T204948Z</version_modified>
<version_id>dbdc851d-c806-4cb6-bdf7-ead9f962fa17</version_id>
<version_modified>20221103T232455Z</version_modified>
<xml_checksum>9339BE01</xml_checksum>
<class_name>ApplyUpgrade</class_name>
<display_name>Apply Upgrade</display_name>
Expand Down Expand Up @@ -6342,7 +6342,7 @@
<filename>measure.rb</filename>
<filetype>rb</filetype>
<usage_type>script</usage_type>
<checksum>ADB8265D</checksum>
<checksum>03D562FD</checksum>
</file>
</files>
</measure>
28 changes: 12 additions & 16 deletions measures/BuildExistingModel/measure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ def run(model, runner, user_arguments)

# Get the absolute paths relative to this meta measure in the run directory
new_runner = OpenStudio::Measure::OSRunner.new(OpenStudio::WorkflowJSON.new) # we want only ResStockArguments registered argument values
if not apply_measures(measures_dir, { 'ResStockArguments' => measures['ResStockArguments'] }, new_runner, model, true, 'OpenStudio::Measure::ModelMeasure', nil)
if not apply_measures(measures_dir, { 'ResStockArguments' => measures['ResStockArguments'] }, new_runner, model, true, 'OpenStudio::Measure::ModelMeasure')
register_logs(runner, new_runner)
return false
end
Expand All @@ -328,6 +328,7 @@ def run(model, runner, user_arguments)
hpxml_path = File.expand_path('../existing.xml')
measures['BuildResidentialHPXML'] = [{ 'hpxml_path' => hpxml_path }]
measures['BuildResidentialScheduleFile'] = [{ 'hpxml_path' => hpxml_path, 'hpxml_output_path' => hpxml_path }]
measures['ResStockArgumentsPostHPXML'] = [{ 'hpxml_path' => hpxml_path }]

new_runner.result.stepValues.each do |step_value|
value = get_value_from_workflow_step_value(step_value)
Expand All @@ -352,7 +353,7 @@ def run(model, runner, user_arguments)
measures['BuildResidentialHPXML'][0]['software_info_program_used'] = 'ResStock'
measures['BuildResidentialHPXML'][0]['software_info_program_version'] = Version::ResStock_Version

# Get registered values and pass them to BuildResidentialHPXML
# Simulation control
measures['BuildResidentialHPXML'][0]['simulation_control_timestep'] = args['simulation_control_timestep'].get if args['simulation_control_timestep'].is_initialized
if args['simulation_control_run_period_begin_month'].is_initialized && args['simulation_control_run_period_begin_day_of_month'].is_initialized && args['simulation_control_run_period_end_month'].is_initialized && args['simulation_control_run_period_end_day_of_month'].is_initialized
begin_month = "#{Date::ABBR_MONTHNAMES[args['simulation_control_run_period_begin_month'].get]}"
Expand Down Expand Up @@ -533,10 +534,13 @@ def run(model, runner, user_arguments)
end
end

# Get registered values and pass them to BuildResidentialScheduleFile
# BuildResidentialScheduleFile
measures['BuildResidentialScheduleFile'][0]['schedules_random_seed'] = args['building_id']
measures['BuildResidentialScheduleFile'][0]['output_csv_path'] = File.expand_path('../schedules.csv')

# ResStockArgumentsPostHPXML
measures['ResStockArgumentsPostHPXML'][0]['output_csv_path'] = File.expand_path('../schedules.csv')

# Specify measures to run
measures['BuildResidentialHPXML'][0]['apply_defaults'] = true # for apply_hvac_sizing
if run_hescore_workflow
Expand All @@ -550,6 +554,11 @@ def run(model, runner, user_arguments)
return false
end

if not apply_measures(measures_dir, { 'ResStockArgumentsPostHPXML' => measures['ResStockArgumentsPostHPXML'] }, new_runner, model, true, 'OpenStudio::Measure::ModelMeasure')
register_logs(runner, new_runner)
return false
end

# Copy existing.xml to home.xml for downstream HPXMLtoOpenStudio
# We need existing.xml (and not just home.xml) for UpgradeCosts
in_path = File.expand_path('../home.xml')
Expand Down Expand Up @@ -602,19 +611,6 @@ def run(model, runner, user_arguments)

return true
end

def register_logs(runner, new_runner)
new_runner.result.warnings.each do |warning|
runner.registerWarning(warning.logMessage)
end
new_runner.result.info.each do |info|
runner.registerInfo(info.logMessage)
end
new_runner.result.errors.each do |error|
runner.registerError(error.logMessage)
end
return
end
end

# register the measure to be used by the application
Expand Down
6 changes: 3 additions & 3 deletions measures/BuildExistingModel/measure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<schema_version>3.0</schema_version>
<name>build_existing_model</name>
<uid>dedf59bb-3b88-4f16-8755-2c1ff5519cbf</uid>
<version_id>0d1f6325-f179-4ec8-9ada-26499f6c4c53</version_id>
<version_modified>20220912T204948Z</version_modified>
<version_id>f9623dc3-d435-4d8d-8610-8ddb8a11017a</version_id>
<version_modified>20221103T232456Z</version_modified>
<xml_checksum>2C38F48B</xml_checksum>
<class_name>BuildExistingModel</class_name>
<display_name>Build Existing Model</display_name>
Expand Down Expand Up @@ -320,7 +320,7 @@
<filename>measure.rb</filename>
<filetype>rb</filetype>
<usage_type>script</usage_type>
<checksum>BB3171DA</checksum>
<checksum>2141FC6D</checksum>
</file>
</files>
</measure>
2 changes: 1 addition & 1 deletion measures/ResStockArguments/measure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def description

# human readable description of modeling approach
def modeler_description
return 'Passes in all arguments from the options lookup, processes them, and then registers values to the runner to be used by other measures.'
return 'Passes in all ResStockArguments arguments from the options lookup, processes them, and then registers values to the runner to be used by other measures.'
end

# define the arguments that the user will input
Expand Down
12 changes: 6 additions & 6 deletions measures/ResStockArguments/measure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
<schema_version>3.0</schema_version>
<name>res_stock_arguments</name>
<uid>c984bb9e-4ac4-4930-a399-9d23f8f6936a</uid>
<version_id>b7ce3066-ca7e-4669-b1a0-502e6347f8f7</version_id>
<version_modified>20221031T170331Z</version_modified>
<version_id>e098131e-a167-4cb8-8295-18ab07e19fb9</version_id>
<version_modified>20221103T222843Z</version_modified>
<xml_checksum>2C38F48B</xml_checksum>
<class_name>ResStockArguments</class_name>
<display_name>ResStock Arguments</display_name>
<description>Measure that pre-processes the arguments passed to the BuildResidentialHPXML and BuildResidentialScheduleFile measures.</description>
<modeler_description>Passes in all arguments from the options lookup, processes them, and then registers values to the runner to be used by other measures.</modeler_description>
<modeler_description>Passes in all ResStockArguments arguments from the options lookup, processes them, and then registers values to the runner to be used by other measures.</modeler_description>
<arguments>
<argument>
<name>schedules_filepaths</name>
Expand Down Expand Up @@ -761,8 +761,8 @@
<display_name>LogWall</display_name>
</choice>
<choice>
<value>StructurallyInsulatedPanel</value>
<display_name>StructurallyInsulatedPanel</display_name>
<value>StructuralInsulatedPanel</value>
<display_name>StructuralInsulatedPanel</display_name>
</choice>
<choice>
<value>SolidConcrete</value>
Expand Down Expand Up @@ -5055,7 +5055,7 @@
<filename>measure.rb</filename>
<filetype>rb</filetype>
<usage_type>script</usage_type>
<checksum>F4AF65BB</checksum>
<checksum>86E1D264</checksum>
</file>
</files>
</measure>
103 changes: 103 additions & 0 deletions measures/ResStockArgumentsPostHPXML/measure.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# frozen_string_literal: true

# see the URL below for information on how to write OpenStudio measures
# http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/

# start the measure
class ResStockArgumentsPostHPXML < OpenStudio::Measure::ModelMeasure
# human readable name
def name
# Measure name should be the title case of the class name.
return 'ResStock Arguments Post-HPXML'
end

# human readable description
def description
return 'Measure that post-processes the output of the BuildResidentialHPXML and BuildResidentialScheduleFile measures.'
end

# human readable description of modeling approach
def modeler_description
return 'Passes in all ResStockArgumentsPostHPXML arguments from the options lookup, processes them, and then modifies output of other measures.'
end

# define the arguments that the user will input
def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
args = OpenStudio::Measure::OSArgumentVector.new

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

arg = OpenStudio::Measure::OSArgument::makeStringArgument('output_csv_path', false)
arg.setDisplayName('Schedules: Output CSV Path')
arg.setDescription('Absolute/relative path of the csv file containing user-specified occupancy schedules. Relative paths are relative to the HPXML output path.')
args << arg

return args
end

# define what happens when the measure is run
def run(model, runner, user_arguments)
super(model, runner, user_arguments)

# use the built-in error checking
if !runner.validateUserArguments(arguments(model), user_arguments)
return false
end

# assign the user inputs to variables
args = get_argument_values(runner, arguments(model), user_arguments)
args = Hash[args.collect { |k, v| [k.to_sym, v] }]

hpxml_path = args[:hpxml_path].get
unless (Pathname.new hpxml_path).absolute?
hpxml_path = File.expand_path(File.join(File.dirname(__FILE__), hpxml_path))
end
unless File.exist?(hpxml_path) && hpxml_path.downcase.end_with?('.xml')
fail "'#{hpxml_path}' does not exist or is not an .xml file."
end

_hpxml = HPXML.new(hpxml_path: hpxml_path)

# init
new_schedules = {}

# TODO: populate new_schedules
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to add the schedules here or is this section just a placeholder for future PRs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a placeholder for future PRs.


# return if not writing schedules
return true if new_schedules.empty?

# write schedules
schedules_filepath = File.join(File.dirname(args[:output_csv_path].get), 'schedules2.csv')
write_new_schedules(new_schedules, schedules_filepath)

# modify the hpxml with the schedules path
doc = XMLHelper.parse_file(hpxml_path)
extension = XMLHelper.create_elements_as_needed(XMLHelper.get_element(doc, '/HPXML'), ['SoftwareInfo', 'extension'])
schedules_filepaths = XMLHelper.get_values(extension, 'SchedulesFilePath', :string)
if !schedules_filepaths.include?(schedules_filepath)
XMLHelper.add_element(extension, 'SchedulesFilePath', schedules_filepath, :string)

# write out the modified hpxml
XMLHelper.write_file(doc, hpxml_path)
runner.registerInfo("Wrote file: #{hpxml_path}")
end

return true
end

def write_new_schedules(schedules, schedules_filepath)
CSV.open(schedules_filepath, 'w') do |csv|
csv << schedules.keys
rows = schedules.values.transpose
rows.each do |row|
csv << row.map { |x| '%.3g' % x }
end
end
end
end

# register the measure to be used by the application
ResStockArgumentsPostHPXML.new.registerWithApplication
Loading