Skip to content

Commit

Permalink
Merge branch 'whole_sfa_mf_models_unit_multiplier' into whole_sfa_mf_…
Browse files Browse the repository at this point in the history
…models_unit_multiplier_schedules
  • Loading branch information
joseph-robertson committed Sep 6, 2023
2 parents f8082a6 + 3363579 commit 32e5d6c
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 16 deletions.
31 changes: 25 additions & 6 deletions HPXMLtoOpenStudio/measure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ def run(model, runner, user_arguments)
epw_path = Location.get_epw_path(hpxml.buildings[0], hpxml_path)
weather = WeatherProcess.new(epw_path: epw_path, runner: runner)
epw_file = OpenStudio::EpwFile.new(epw_path)
hpxml.buildings.each_with_index do |hpxml_bldg, i|
next if i == 0
next if Location.get_epw_path(hpxml_bldg, hpxml_path) == epw_path

fail 'Weather station EPW filepath has different values across dwelling units.'
end

# Apply HPXML defaults upfront; process schedules & emissions
check_emissions_references(hpxml.header, hpxml_path)
Expand Down Expand Up @@ -224,15 +230,30 @@ def add_unit_model_to_model(model, hpxml_osm_map)

# Handle unique objects first: Grab one from the first model we find the
# object on (may not be the first unit).
# FIXME: Need to throw a warning/error if different values between the model
# object and unit_model object.
uuid_regex = /\{(.*?)\}/
unique_objects.each do |idd_obj, osm_class|
first_model_object = nil
hpxml_osm_map.values.each do |unit_model|
next if unit_model.getObjectsByType(idd_obj.to_IddObjectType).empty?

unit_model_objects << unit_model.send("get#{osm_class}")
break
model_object = unit_model.send("get#{osm_class}")
if first_model_object.nil?
first_model_object = model_object
else
# Throw error if different values between this model_object and first_model_object
if model_object.to_s.gsub(uuid_regex, '') != first_model_object.to_s.gsub(uuid_regex, '')
fail "Unique object (#{idd_obj}) has different values across dwelling units."
end

# Need to check any referenced child objects too
if idd_obj == 'OS:Site:WaterMainsTemperature'
if model_object.temperatureSchedule.get.to_s.gsub(uuid_regex, '') != first_model_object.temperatureSchedule.get.to_s.gsub(uuid_regex, '')
fail "Unique object (#{idd_obj}) has different values across dwelling units."
end
end
end
end
unit_model_objects << first_model_object unless first_model_object.nil?
end

hpxml_osm_map.values.each_with_index do |unit_model, unit_number|
Expand Down Expand Up @@ -403,7 +424,6 @@ def create_unit_model(hpxml, hpxml_bldg, runner, model, epw_path, epw_file, weat
# Init
OpenStudio::Model::WeatherFile.setWeatherFile(model, epw_file)
set_defaults_and_globals()
# FIXME: Need to address this
Location.apply(model, weather, epw_file, @hpxml_header, @hpxml_bldg)
add_simulation_params(model)

Expand Down Expand Up @@ -545,7 +565,6 @@ def set_defaults_and_globals()
end

def add_simulation_params(model)
# FIXME: Address this
SimControls.apply(model, @hpxml_header, @hpxml_bldg)
end

Expand Down
8 changes: 4 additions & 4 deletions HPXMLtoOpenStudio/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>hpxm_lto_openstudio</name>
<uid>b1543b30-9465-45ff-ba04-1d1f85e763bc</uid>
<version_id>4b5d38e3-9a0d-49c7-8a63-1a3a61a22983</version_id>
<version_modified>2023-09-06T22:21:20Z</version_modified>
<version_id>557ba292-fbd5-4dd2-89e4-7780be6d1745</version_id>
<version_modified>2023-09-06T22:22:50Z</version_modified>
<xml_checksum>D8922A73</xml_checksum>
<class_name>HPXMLtoOpenStudio</class_name>
<display_name>HPXML to OpenStudio Translator</display_name>
Expand Down Expand Up @@ -130,7 +130,7 @@
<filename>measure.rb</filename>
<filetype>rb</filetype>
<usage_type>script</usage_type>
<checksum>98E3DC35</checksum>
<checksum>FC66F31B</checksum>
</file>
<file>
<filename>airflow.rb</filename>
Expand Down Expand Up @@ -568,7 +568,7 @@
<filename>test_validation.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>37D8B7FD</checksum>
<checksum>B4683C59</checksum>
</file>
<file>
<filename>test_water_heater.rb</filename>
Expand Down
41 changes: 35 additions & 6 deletions HPXMLtoOpenStudio/tests/test_validation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -898,10 +898,14 @@ def test_ruby_error_messages
'unattached-shared-dishwasher-dhw-distribution' => ["Attached hot water distribution 'foobar' not found for dishwasher"],
'unattached-shared-dishwasher-water-heater' => ["Attached water heating system 'foobar' not found for dishwasher"],
'unattached-window' => ["Attached wall 'foobar' not found for window 'Window1'."],
'unavailable-period-missing-column' => ["Could not find column='foobar' in unavailable_periods.csv."] }
'unavailable-period-missing-column' => ["Could not find column='foobar' in unavailable_periods.csv."],
'unique-objects-vary-across-units-epw' => ['Weather station EPW filepath has different values across dwelling units.'],
'unique-objects-vary-across-units-dst' => ['Unique object (OS:RunPeriodControl:DaylightSavingTime) has different values across dwelling units.'],
'unique-objects-vary-across-units-tmains' => ['Unique object (OS:Site:WaterMainsTemperature) has different values across dwelling units.'] }

all_expected_errors.each_with_index do |(error_case, expected_errors), i|
puts "[#{i + 1}/#{all_expected_errors.size}] Testing #{error_case}..."
building_id = nil
# Create HPXML object
if ['battery-bad-values-max-not-one'].include? error_case
hpxml, hpxml_bldg = _create_hpxml('base-battery-scheduled.xml')
Expand Down Expand Up @@ -1253,6 +1257,23 @@ def test_ruby_error_messages
elsif ['unavailable-period-missing-column'].include? error_case
hpxml, _hpxml_bldg = _create_hpxml('base-schedules-simple-vacancy.xml')
hpxml.header.unavailable_periods[0].column_name = 'foobar'
elsif ['unique-objects-vary-across-units-epw'].include? error_case
building_id = 'ALL'
hpxml, hpxml_bldg = _create_hpxml('base-multiple-buildings.xml', building_id: building_id)
hpxml_bldg.climate_and_risk_zones.weather_station_epw_filepath = 'USA_AZ_Phoenix-Sky.Harbor.Intl.AP.722780_TMY3.epw'
elsif ['unique-objects-vary-across-units-dst'].include? error_case
building_id = 'ALL'
hpxml, hpxml_bldg = _create_hpxml('base-multiple-buildings.xml', building_id: building_id)
hpxml_bldg.dst_begin_month = 3
hpxml_bldg.dst_begin_day = 15
hpxml_bldg.dst_end_month = 10
hpxml_bldg.dst_end_day = 15
elsif ['unique-objects-vary-across-units-tmains'].include? error_case
building_id = 'ALL'
hpxml, hpxml_bldg = _create_hpxml('base-multiple-buildings.xml', building_id: building_id)
hpxml_bldg.hot_water_distributions[0].dwhr_facilities_connected = HPXML::DWHRFacilitiesConnectedOne
hpxml_bldg.hot_water_distributions[0].dwhr_equal_flow = true
hpxml_bldg.hot_water_distributions[0].dwhr_efficiency = 0.55
else
fail "Unhandled case: #{error_case}."
end
Expand All @@ -1272,7 +1293,7 @@ def test_ruby_error_messages
end

XMLHelper.write_file(hpxml_doc, @tmp_hpxml_path)
_test_measure('error', expected_errors)
_test_measure('error', expected_errors, building_id: building_id)
end
end

Expand Down Expand Up @@ -1360,6 +1381,7 @@ def test_ruby_warning_messages

all_expected_warnings.each_with_index do |(warning_case, expected_warnings), i|
puts "[#{i + 1}/#{all_expected_warnings.size}] Testing #{warning_case}..."
building_id = nil
# Create HPXML object
if ['cfis-undersized-supplemental-fan'].include? warning_case
hpxml, hpxml_bldg = _create_hpxml('base-mechvent-cfis-supplemental-fan-exhaust.xml')
Expand Down Expand Up @@ -1430,7 +1452,7 @@ def test_ruby_warning_messages
hpxml_doc = hpxml.to_doc()

XMLHelper.write_file(hpxml_doc, @tmp_hpxml_path)
_test_measure('warning', expected_warnings)
_test_measure('warning', expected_warnings, building_id: building_id)
end
end

Expand All @@ -1454,7 +1476,7 @@ def _test_schema_and_schematron_validation(hpxml_path, hpxml_doc, expected_error
end
end

def _test_measure(error_or_warning, expected_errors_or_warnings)
def _test_measure(error_or_warning, expected_errors_or_warnings, building_id: nil)
# create an instance of the measure
measure = HPXMLtoOpenStudio.new

Expand All @@ -1466,6 +1488,7 @@ def _test_measure(error_or_warning, expected_errors_or_warnings)
args_hash['hpxml_path'] = File.absolute_path(@tmp_hpxml_path)
args_hash['debug'] = true
args_hash['output_dir'] = File.absolute_path(@tmp_output_path)
args_hash['building_id'] = building_id unless building_id.nil?
arguments = measure.arguments(model)
argument_map = OpenStudio::Measure.convertOSArgumentVectorToMap(arguments)

Expand Down Expand Up @@ -1529,8 +1552,14 @@ def _compare_errors_or_warnings(type, actual_msgs, expected_msgs)
end
end

def _create_hpxml(hpxml_name)
hpxml = HPXML.new(hpxml_path: File.join(@sample_files_path, hpxml_name))
def _create_hpxml(hpxml_name, building_id: nil)
hpxml = HPXML.new(hpxml_path: File.join(@sample_files_path, hpxml_name), building_id: building_id)
if not hpxml.errors.empty?
hpxml.errors.each do |error|
puts error
end
flunk "Did not successfully create HPXML file: #{hpxml_name}"
end
return hpxml, hpxml.buildings[0]
end
end

0 comments on commit 32e5d6c

Please sign in to comment.