From f98754ece38329079983634359f233a04b59f734 Mon Sep 17 00:00:00 2001 From: Scott Horowitz Date: Thu, 29 Aug 2024 09:23:03 -0600 Subject: [PATCH 1/4] Clean up docs/schematron related to CFIS FanPower and VentilationOnlyModeAirflowFraction inputs. --- HPXMLtoOpenStudio/resources/hpxml_defaults.rb | 1 + .../hpxml_schematron/EPvalidator.xml | 27 +++++++++++++------ docs/source/workflow_inputs.rst | 3 ++- workflow/hpxml_inputs.json | 9 ++++--- ...se-mechvent-cfis-no-additional-runtime.xml | 1 - ...mechvent-cfis-supplemental-fan-exhaust.xml | 1 - ...-mechvent-cfis-supplemental-fan-supply.xml | 1 - 7 files changed, 28 insertions(+), 15 deletions(-) diff --git a/HPXMLtoOpenStudio/resources/hpxml_defaults.rb b/HPXMLtoOpenStudio/resources/hpxml_defaults.rb index 5dc0f95eb9..c032ca0860 100644 --- a/HPXMLtoOpenStudio/resources/hpxml_defaults.rb +++ b/HPXMLtoOpenStudio/resources/hpxml_defaults.rb @@ -2553,6 +2553,7 @@ def self.apply_ventilation_fans(hpxml_bldg, weather, cfa, nbeds, eri_version) end if vent_fan.fan_power.nil? + # FIXME: CFIS W/cfm should apply to total air handler cfm in ventilation only mode, not just outdoor air cfm vent_fan.fan_power = (vent_fan.flow_rate * Airflow.get_default_mech_vent_fan_power(vent_fan, eri_version)).round(1) vent_fan.fan_power_isdefaulted = true end diff --git a/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml b/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml index 2cb6b07991..5a6614c7e8 100644 --- a/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml +++ b/HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml @@ -1998,13 +1998,20 @@ Expected 0 element(s) for xpath: IsSharedSystem[text()="true"] Expected 0 or 1 element(s) for xpath: CFISControls/AdditionalRuntimeOperatingMode - Expected CFISControls/AdditionalRuntimeOperatingMode to be 'air handler fan' or 'supplemental fan' or 'none' + Expected CFISControls/AdditionalRuntimeOperatingMode to be 'air handler fan' or 'supplemental fan' or 'none' Expected 0 or more element(s) for xpath: RatedFlowRate | CalculatedFlowRate | TestedFlowRate | DeliveredVentilation Expected 0 or 1 element(s) for xpath: HoursInOperation Expected 0 element(s) for xpath: TotalRecoveryEfficiency | AdjustedTotalRecoveryEfficiency Expected 0 element(s) for xpath: SensibleRecoveryEfficiency | AdjustedSensibleRecoveryEfficiency - Expected 0 or 1 element(s) for xpath: FanPower Expected 1 element(s) for xpath: AttachedToHVACDistributionSystem + + + + + [CFISAdditionalRuntimeMode=AirHandlerFan] + + Expected 0 element(s) for xpath: CFISControls/SupplementalFan + Expected 0 or 1 element(s) for xpath: FanPower Expected 0 or 1 element(s) for xpath: extension/VentilationOnlyModeAirflowFraction Expected extension/VentilationOnlyModeAirflowFraction to be greater than or equal to 0 Expected extension/VentilationOnlyModeAirflowFraction to be less than or equal to 1 @@ -2012,16 +2019,20 @@ - [MechanicalVentilationType=CFISWithSupplementalFan] - - Expected 1 element(s) for xpath: SupplementalFan + [CFISAdditionalRuntimeMode=SupplementalFan] + + Expected 1 element(s) for xpath: CFISControls/SupplementalFan + Expected 0 element(s) for xpath: FanPower + Expected 0 element(s) for xpath: extension/VentilationOnlyModeAirflowFraction - [MechanicalVentilationType=CFISWithoutSupplementalFan] - - Expected 0 element(s) for xpath: SupplementalFan + [CFISAdditionalRuntimeMode=None] + + Expected 0 element(s) for xpath: CFISControls/SupplementalFan + Expected 0 element(s) for xpath: FanPower + Expected 0 element(s) for xpath: extension/VentilationOnlyModeAirflowFraction diff --git a/docs/source/workflow_inputs.rst b/docs/source/workflow_inputs.rst index 12a9ddcce1..e56121cb7e 100644 --- a/docs/source/workflow_inputs.rst +++ b/docs/source/workflow_inputs.rst @@ -3527,7 +3527,7 @@ Each central fan integrated supply (CFIS) system is entered as a ``/HPXML/Buildi ``CFISControls/SupplementalFan`` idref See [#]_ See [#]_ The supplemental fan providing additional ventilation ``RatedFlowRate`` or ``TestedFlowRate`` or ``CalculatedFlowRate`` or ``DeliveredVentilation`` double cfm >= 0 No See [#]_ Flow rate [#]_ ``HoursInOperation`` double hrs/day >= 0, <= 24 false 8 Hours per day of operation [#]_ - ``FanPower`` double W >= 0 No See [#]_ Fan power + ``FanPower`` double W >= 0 No [#]_ See [#]_ Blower fan power during ventilation only mode ``AttachedToHVACDistributionSystem`` idref See [#]_ Yes ID of attached distribution system ``extension/VentilationOnlyModeAirflowFraction`` double frac >= 0, <= 1 No 1.0 Blower airflow rate fraction during ventilation only mode [#]_ ============================================================================================= ======== ======= ============================= ======== =============== ========================================= @@ -3554,6 +3554,7 @@ Each central fan integrated supply (CFIS) system is entered as a ``/HPXML/Buildi .. [#] The flow rate should equal the amount of outdoor air provided to the distribution system, not the total airflow through the distribution system. .. [#] HoursInOperation is combined with the flow rate to form the hourly target ventilation rate (e.g., inputs of 90 cfm and 8 hrs/day produce an hourly target ventilation rate of 30 cfm). + .. [#] FanPower only applies when AdditionalRuntimeOperatingMode="air handler fan", in which it determines the blower fan power during ventilation only mode. .. [#] If FanPower not provided, defaults to 0.58 W/cfm based on ANSI/RESNET/ICC 301-2022 Addendum C. .. [#] HVACDistribution type cannot be :ref:`hvac_distribution_hydronic`. .. [#] VentilationOnlyModeAirflowFraction only applies when AdditionalRuntimeOperatingMode="air handler fan". diff --git a/workflow/hpxml_inputs.json b/workflow/hpxml_inputs.json index 6a187a8187..c3e42027ac 100644 --- a/workflow/hpxml_inputs.json +++ b/workflow/hpxml_inputs.json @@ -3147,13 +3147,16 @@ "mech_vent_num_units_served": 1 }, "sample_files/base-mechvent-cfis-no-additional-runtime.xml": { - "parent_hpxml": "sample_files/base-mechvent-cfis.xml" + "parent_hpxml": "sample_files/base-mechvent-cfis.xml", + "mech_vent_fan_power": null }, "sample_files/base-mechvent-cfis-supplemental-fan-exhaust.xml": { - "parent_hpxml": "sample_files/base-mechvent-cfis.xml" + "parent_hpxml": "sample_files/base-mechvent-cfis.xml", + "mech_vent_fan_power": null }, "sample_files/base-mechvent-cfis-supplemental-fan-supply.xml": { - "parent_hpxml": "sample_files/base-mechvent-cfis.xml" + "parent_hpxml": "sample_files/base-mechvent-cfis.xml", + "mech_vent_fan_power": null }, "sample_files/base-mechvent-erv.xml": { "parent_hpxml": "sample_files/base.xml", diff --git a/workflow/sample_files/base-mechvent-cfis-no-additional-runtime.xml b/workflow/sample_files/base-mechvent-cfis-no-additional-runtime.xml index acd8b19d9e..3e80429abe 100644 --- a/workflow/sample_files/base-mechvent-cfis-no-additional-runtime.xml +++ b/workflow/sample_files/base-mechvent-cfis-no-additional-runtime.xml @@ -404,7 +404,6 @@ 330.0 8.0 true - 300.0 diff --git a/workflow/sample_files/base-mechvent-cfis-supplemental-fan-exhaust.xml b/workflow/sample_files/base-mechvent-cfis-supplemental-fan-exhaust.xml index 86aee35f80..0dd27ea640 100644 --- a/workflow/sample_files/base-mechvent-cfis-supplemental-fan-exhaust.xml +++ b/workflow/sample_files/base-mechvent-cfis-supplemental-fan-exhaust.xml @@ -405,7 +405,6 @@ 330.0 8.0 true - 300.0 diff --git a/workflow/sample_files/base-mechvent-cfis-supplemental-fan-supply.xml b/workflow/sample_files/base-mechvent-cfis-supplemental-fan-supply.xml index 66f32265d3..1846df40d0 100644 --- a/workflow/sample_files/base-mechvent-cfis-supplemental-fan-supply.xml +++ b/workflow/sample_files/base-mechvent-cfis-supplemental-fan-supply.xml @@ -405,7 +405,6 @@ 330.0 8.0 true - 300.0 From ba1239ddf0f7f1ff3c15c6779841a9eb28847325 Mon Sep 17 00:00:00 2001 From: Scott Horowitz Date: Thu, 29 Aug 2024 11:44:11 -0600 Subject: [PATCH 2/4] Address CI failures --- HPXMLtoOpenStudio/measure.xml | 18 ++++---- HPXMLtoOpenStudio/resources/airflow.rb | 2 +- HPXMLtoOpenStudio/resources/hpxml.rb | 5 +++ HPXMLtoOpenStudio/resources/hpxml_defaults.rb | 12 +++--- HPXMLtoOpenStudio/tests/test_airflow.rb | 2 +- HPXMLtoOpenStudio/tests/test_defaults.rb | 43 +++++++++++++------ HPXMLtoOpenStudio/tests/test_validation.rb | 6 +-- tasks.rb | 1 - .../sample_files/base-mechvent-multiple.xml | 1 - 9 files changed, 55 insertions(+), 35 deletions(-) diff --git a/HPXMLtoOpenStudio/measure.xml b/HPXMLtoOpenStudio/measure.xml index abf815c5df..dac93b406f 100644 --- a/HPXMLtoOpenStudio/measure.xml +++ b/HPXMLtoOpenStudio/measure.xml @@ -3,8 +3,8 @@ 3.1 hpxm_lto_openstudio b1543b30-9465-45ff-ba04-1d1f85e763bc - 6f1b71cd-073a-4b20-bbc1-1e4d5ce1a151 - 2024-08-28T20:08:55Z + 54957d8f-0214-4cb8-9987-79151eb86dc8 + 2024-08-29T17:40:04Z D8922A73 HPXMLtoOpenStudio HPXML to OpenStudio Translator @@ -189,7 +189,7 @@ airflow.rb rb resource - 6D51E306 + B318F464 battery.rb @@ -357,13 +357,13 @@ hpxml.rb rb resource - 9222D4D6 + C45A51AE hpxml_defaults.rb rb resource - 6EC55ED7 + 70E11338 hpxml_schema/HPXML.xsd @@ -381,7 +381,7 @@ hpxml_schematron/EPvalidator.xml xml resource - AE956548 + 5C33FE12 hpxml_schematron/iso-schematron.xsd @@ -645,7 +645,7 @@ test_airflow.rb rb test - B8A66D0B + 171B5E6D test_battery.rb @@ -657,7 +657,7 @@ test_defaults.rb rb test - CBD787A1 + 8AFB237F test_enclosure.rb @@ -729,7 +729,7 @@ test_validation.rb rb test - 6EDC8C3A + C621EC4A test_water_heater.rb diff --git a/HPXMLtoOpenStudio/resources/airflow.rb b/HPXMLtoOpenStudio/resources/airflow.rb index 98bb6fbf5a..b1a10db2b0 100644 --- a/HPXMLtoOpenStudio/resources/airflow.rb +++ b/HPXMLtoOpenStudio/resources/airflow.rb @@ -1846,7 +1846,6 @@ def self.apply_cfis(infil_program, vent_mech_fans, cfis_fan_actuator, cfis_suppl @fan_rtf_sensor[@cfis_airloop[vent_mech.id]].each do |rtf_sensor| infil_program.addLine("Set fan_rtf_hvac = fan_rtf_hvac + #{rtf_sensor.name}") end - infil_program.addLine("Set cfis_fan_w = #{vent_mech.unit_fan_power}") # W infil_program.addLine('If @ABS(Minute - ZoneTimeStep*60) < 0.1') infil_program.addLine(" Set #{@cfis_t_sum_open_var[vent_mech.id].name} = 0") # New hour, time on summation re-initializes to 0 @@ -1868,6 +1867,7 @@ def self.apply_cfis(infil_program, vent_mech_fans, cfis_fan_actuator, cfis_suppl infil_program.addLine(" Set #{@cfis_f_damper_extra_open_var[vent_mech.id].name} = @Max (cfis_f_damper_open - fan_rtf_hvac) 0.0") if vent_mech.cfis_addtl_runtime_operating_mode == HPXML::CFISModeAirHandler # Air handler meets additional runtime requirement + infil_program.addLine("Set cfis_fan_w = #{vent_mech.unit_fan_power}") # W infil_program.addLine(" Set #{cfis_fan_actuator.name} = #{cfis_fan_actuator.name} + cfis_fan_w * #{@cfis_f_damper_extra_open_var[vent_mech.id].name}") elsif vent_mech.cfis_addtl_runtime_operating_mode == HPXML::CFISModeSupplementalFan if vent_mech.cfis_supplemental_fan.oa_unit_flow_rate < vent_mech.average_unit_flow_rate diff --git a/HPXMLtoOpenStudio/resources/hpxml.rb b/HPXMLtoOpenStudio/resources/hpxml.rb index e480c214cd..f0542a9cf1 100644 --- a/HPXMLtoOpenStudio/resources/hpxml.rb +++ b/HPXMLtoOpenStudio/resources/hpxml.rb @@ -8113,6 +8113,11 @@ def is_cfis_supplemental_fan # # @return [nil] def delete + if is_cfis_supplemental_fan + @parent_object.ventilation_fans.each do |vent_fan| + vent_fan.cfis_supplemental_fan_idref = nil if vent_fan.cfis_supplemental_fan_idref == @id + end + end @parent_object.ventilation_fans.delete(self) end diff --git a/HPXMLtoOpenStudio/resources/hpxml_defaults.rb b/HPXMLtoOpenStudio/resources/hpxml_defaults.rb index 53add9a15a..b12d1ce93b 100644 --- a/HPXMLtoOpenStudio/resources/hpxml_defaults.rb +++ b/HPXMLtoOpenStudio/resources/hpxml_defaults.rb @@ -2579,21 +2579,21 @@ def self.apply_ventilation_fans(hpxml_bldg, weather, cfa, nbeds, eri_version) vent_fan.rated_flow_rate_isdefaulted = true end - if vent_fan.fan_power.nil? - # FIXME: CFIS W/cfm should apply to total air handler cfm in ventilation only mode, not just outdoor air cfm + if vent_fan.fan_power.nil? && vent_fan.fan_type != HPXML::MechVentTypeCFIS + # FIXME: CFIS fan power (for mode == HPXML::CFISModeAirHandler) needs to be applied after total air handler cfm is determined vent_fan.fan_power = (vent_fan.flow_rate * Airflow.get_default_mech_vent_fan_power(vent_fan, eri_version)).round(1) vent_fan.fan_power_isdefaulted = true end next unless vent_fan.fan_type == HPXML::MechVentTypeCFIS - if vent_fan.cfis_vent_mode_airflow_fraction.nil? - vent_fan.cfis_vent_mode_airflow_fraction = 1.0 - vent_fan.cfis_vent_mode_airflow_fraction_isdefaulted = true - end if vent_fan.cfis_addtl_runtime_operating_mode.nil? vent_fan.cfis_addtl_runtime_operating_mode = HPXML::CFISModeAirHandler vent_fan.cfis_addtl_runtime_operating_mode_isdefaulted = true end + if vent_fan.cfis_vent_mode_airflow_fraction.nil? && (vent_fan.cfis_addtl_runtime_operating_mode == HPXML::CFISModeAirHandler) + vent_fan.cfis_vent_mode_airflow_fraction = 1.0 + vent_fan.cfis_vent_mode_airflow_fraction_isdefaulted = true + end end # Default kitchen fan diff --git a/HPXMLtoOpenStudio/tests/test_airflow.rb b/HPXMLtoOpenStudio/tests/test_airflow.rb index 2c07fa2107..a345e7c402 100644 --- a/HPXMLtoOpenStudio/tests/test_airflow.rb +++ b/HPXMLtoOpenStudio/tests/test_airflow.rb @@ -488,7 +488,7 @@ def test_multiple_mechvent vent_fan_power_ervhrv = vent_fan_ervhrv.map { |f| f.average_unit_fan_power }.sum(0.0) vent_fan_cfis = whole_fans.select { |f| f.fan_type == HPXML::MechVentTypeCFIS } vent_fan_cfm_cfis = vent_fan_cfis.map { |f| f.oa_unit_flow_rate }.sum(0.0) - vent_fan_power_cfis = vent_fan_cfis.map { |f| f.fan_power }.sum(0.0) + vent_fan_power_cfis = vent_fan_cfis.select { |f| f.cfis_addtl_runtime_operating_mode == HPXML::CFISModeAirHandler }.map { |f| f.fan_power }.sum(0.0) vent_fan_mins_cfis = vent_fan_cfis.map { |f| f.hours_in_operation / 24.0 * 60.0 }.sum(0.0) # total mech vent fan power excluding cfis diff --git a/HPXMLtoOpenStudio/tests/test_defaults.rb b/HPXMLtoOpenStudio/tests/test_defaults.rb index 5bbde06eb9..5553bd33a2 100644 --- a/HPXMLtoOpenStudio/tests/test_defaults.rb +++ b/HPXMLtoOpenStudio/tests/test_defaults.rb @@ -2811,23 +2811,36 @@ def test_mech_ventilation_fans # Test inputs not overridden by defaults w/ CFIS hpxml, hpxml_bldg = _create_hpxml('base-mechvent-cfis.xml') vent_fan = hpxml_bldg.ventilation_fans.find { |f| f.used_for_whole_building_ventilation } - vent_fan.is_shared_system = false vent_fan.hours_in_operation = 12.0 vent_fan.fan_power = 12.5 vent_fan.rated_flow_rate = 222.0 vent_fan.cfis_vent_mode_airflow_fraction = 0.5 - vent_fan.cfis_addtl_runtime_operating_mode = HPXML::CFISModeSupplementalFan - hpxml_bldg.ventilation_fans.add(id: "VentilationFan#{hpxml_bldg.ventilation_fans.size + 1}", - tested_flow_rate: 79.0, - fan_power: 9.0, - fan_type: HPXML::MechVentTypeExhaust, - is_shared_system: false, - used_for_whole_building_ventilation: true) - suppl_vent_fan = hpxml_bldg.ventilation_fans[-1] - vent_fan.cfis_supplemental_fan_idref = suppl_vent_fan.id XMLHelper.write_file(hpxml.to_doc, @tmp_hpxml_path) _default_hpxml, default_hpxml_bldg = _test_measure() - _test_default_mech_vent_values(default_hpxml_bldg, false, 12.0, 12.5, 222.0, 0.5, HPXML::CFISModeSupplementalFan) + _test_default_mech_vent_values(default_hpxml_bldg, false, 12.0, 12.5, 222.0, 0.5, HPXML::CFISModeAirHandler) + + # Test defaults w/ CFIS + vent_fan.is_shared_system = nil + vent_fan.hours_in_operation = nil + vent_fan.fan_power = nil + vent_fan.rated_flow_rate = nil + vent_fan.cfis_vent_mode_airflow_fraction = nil + vent_fan.cfis_addtl_runtime_operating_mode = nil + XMLHelper.write_file(hpxml.to_doc, @tmp_hpxml_path) + _default_hpxml, default_hpxml_bldg = _test_measure() + _test_default_mech_vent_values(default_hpxml_bldg, false, 8.0, nil, 305.4, 1.0, HPXML::CFISModeAirHandler) + + # Test inputs not overridden by defaults w/ CFIS & supplemental fan + hpxml, hpxml_bldg = _create_hpxml('base-mechvent-cfis-supplemental-fan-exhaust.xml') + vent_fan = hpxml_bldg.ventilation_fans.find { |f| f.used_for_whole_building_ventilation && f.fan_type == HPXML::MechVentTypeCFIS } + vent_fan.hours_in_operation = 12.0 + vent_fan.rated_flow_rate = 222.0 + suppl_vent_fan = vent_fan.cfis_supplemental_fan + suppl_vent_fan.tested_flow_rate = 79.0 + suppl_vent_fan.fan_power = 9.0 + XMLHelper.write_file(hpxml.to_doc, @tmp_hpxml_path) + _default_hpxml, default_hpxml_bldg = _test_measure() + _test_default_mech_vent_values(default_hpxml_bldg, false, 12.0, nil, 222.0, nil, HPXML::CFISModeSupplementalFan) _test_default_mech_vent_suppl_values(default_hpxml_bldg, false, nil, 9.0, 79.0) # Test defaults w/ CFIS supplemental fan @@ -2847,7 +2860,7 @@ def test_mech_ventilation_fans vent_fan.cfis_addtl_runtime_operating_mode = nil XMLHelper.write_file(hpxml.to_doc, @tmp_hpxml_path) _default_hpxml, default_hpxml_bldg = _test_measure() - _test_default_mech_vent_values(default_hpxml_bldg, false, 8.0, 177.1, 305.4, 1.0, HPXML::CFISModeAirHandler) + _test_default_mech_vent_values(default_hpxml_bldg, false, 8.0, nil, 305.4, 1.0, HPXML::CFISModeAirHandler) # Test inputs not overridden by defaults w/ ERV hpxml, hpxml_bldg = _create_hpxml('base-mechvent-erv.xml') @@ -5221,7 +5234,11 @@ def _test_default_mech_vent_values(hpxml_bldg, is_shared_system, hours_in_operat assert_equal(is_shared_system, vent_fan.is_shared_system) assert_equal(hours_in_operation, vent_fan.hours_in_operation) - assert_in_delta(fan_power, vent_fan.fan_power, 0.1) + if fan_power.nil? + assert_nil(vent_fan.fan_power) + else + assert_in_delta(fan_power, vent_fan.fan_power, 0.1) + end assert_in_delta(flow_rate, vent_fan.rated_flow_rate.to_f + vent_fan.calculated_flow_rate.to_f + vent_fan.tested_flow_rate.to_f + vent_fan.delivered_ventilation.to_f, 0.1) if cfis_vent_mode_airflow_fraction.nil? assert_nil(vent_fan.cfis_vent_mode_airflow_fraction) diff --git a/HPXMLtoOpenStudio/tests/test_validation.rb b/HPXMLtoOpenStudio/tests/test_validation.rb index e27364940f..2aed206836 100644 --- a/HPXMLtoOpenStudio/tests/test_validation.rb +++ b/HPXMLtoOpenStudio/tests/test_validation.rb @@ -233,7 +233,7 @@ def test_schema_schematron_error_messages 'missing-attached-to-zone' => ['Expected 1 element(s) for xpath: AttachedToZone'], 'missing-capacity-detailed-performance' => ['Expected 1 element(s) for xpath: ../../../HeatingCapacity', 'Expected 1 element(s) for xpath: ../../../CoolingCapacity'], - 'missing-cfis-supplemental-fan' => ['Expected 1 element(s) for xpath: SupplementalFan'], + 'missing-cfis-supplemental-fan' => ['Expected 1 element(s) for xpath: CFISControls/SupplementalFan'], 'missing-distribution-cfa-served' => ['Expected 1 element(s) for xpath: ../../../ConditionedFloorAreaServed [context: /HPXML/Building/BuildingDetails/Systems/HVAC/HVACDistribution/DistributionSystemType/AirDistribution/Ducts[not(DuctSurfaceArea)], id: "Ducts2"]'], 'missing-duct-area' => ['Expected 1 or more element(s) for xpath: FractionDuctArea | DuctSurfaceArea [context: /HPXML/Building/BuildingDetails/Systems/HVAC/HVACDistribution/DistributionSystemType/AirDistribution/Ducts[DuctLocation], id: "Ducts2"]'], 'missing-duct-location' => ['Expected 0 element(s) for xpath: FractionDuctArea | DuctSurfaceArea [context: /HPXML/Building/BuildingDetails/Systems/HVAC/HVACDistribution/DistributionSystemType/AirDistribution/Ducts[not(DuctLocation)], id: "Ducts2"]'], @@ -692,8 +692,8 @@ def test_schema_schematron_error_messages hpxml_bldg.heat_pumps[0].cooling_capacity = nil hpxml_bldg.heat_pumps[0].heating_capacity = nil elsif ['missing-cfis-supplemental-fan'].include? error_case - hpxml, hpxml_bldg = _create_hpxml('base-mechvent-cfis.xml') - hpxml_bldg.ventilation_fans[0].cfis_addtl_runtime_operating_mode = HPXML::CFISModeSupplementalFan + hpxml, hpxml_bldg = _create_hpxml('base-mechvent-cfis-supplemental-fan-exhaust.xml') + hpxml_bldg.ventilation_fans[1].delete elsif ['missing-distribution-cfa-served'].include? error_case hpxml, hpxml_bldg = _create_hpxml('base.xml') hpxml_bldg.hvac_distributions[0].ducts[1].duct_surface_area = nil diff --git a/tasks.rb b/tasks.rb index 2ab5edb35c..7346fe0934 100644 --- a/tasks.rb +++ b/tasks.rb @@ -2211,7 +2211,6 @@ def apply_hpxml_modification_sample_files(hpxml_path, hpxml) fan_type: HPXML::MechVentTypeCFIS, tested_flow_rate: 42.5, hours_in_operation: 8, - fan_power: 37.5, used_for_whole_building_ventilation: true, cfis_addtl_runtime_operating_mode: HPXML::CFISModeSupplementalFan, cfis_supplemental_fan_idref: hpxml_bldg.ventilation_fans.find { |f| f.fan_type == HPXML::MechVentTypeExhaust }.id, diff --git a/workflow/sample_files/base-mechvent-multiple.xml b/workflow/sample_files/base-mechvent-multiple.xml index 0065c3ffc2..e7a4826b70 100644 --- a/workflow/sample_files/base-mechvent-multiple.xml +++ b/workflow/sample_files/base-mechvent-multiple.xml @@ -627,7 +627,6 @@ 42.5 8.0 true - 37.5 From b26f7748d4e2eaa55cce26370a3f8353ad4e6b95 Mon Sep 17 00:00:00 2001 From: Scott Horowitz Date: Thu, 29 Aug 2024 13:42:55 -0600 Subject: [PATCH 3/4] A few more fixes. --- HPXMLtoOpenStudio/measure.xml | 6 +++--- HPXMLtoOpenStudio/tests/test_airflow.rb | 2 -- workflow/tests/ACCA_Examples/Bob_Ross_Residence.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-1.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-12.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-13.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-15.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-16.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-17.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-2.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-22.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-23.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-3.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-5.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-6.xml | 1 + workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-7.xml | 1 + workflow/tests/ACCA_Examples/Walker_Residence.xml | 1 + 17 files changed, 18 insertions(+), 5 deletions(-) diff --git a/HPXMLtoOpenStudio/measure.xml b/HPXMLtoOpenStudio/measure.xml index dac93b406f..c39e4d8079 100644 --- a/HPXMLtoOpenStudio/measure.xml +++ b/HPXMLtoOpenStudio/measure.xml @@ -3,8 +3,8 @@ 3.1 hpxm_lto_openstudio b1543b30-9465-45ff-ba04-1d1f85e763bc - 54957d8f-0214-4cb8-9987-79151eb86dc8 - 2024-08-29T17:40:04Z + 9ecd1008-2053-4712-9084-a36f4836271c + 2024-08-29T19:42:42Z D8922A73 HPXMLtoOpenStudio HPXML to OpenStudio Translator @@ -645,7 +645,7 @@ test_airflow.rb rb test - 171B5E6D + F88382CC test_battery.rb diff --git a/HPXMLtoOpenStudio/tests/test_airflow.rb b/HPXMLtoOpenStudio/tests/test_airflow.rb index a345e7c402..4dcc20d077 100644 --- a/HPXMLtoOpenStudio/tests/test_airflow.rb +++ b/HPXMLtoOpenStudio/tests/test_airflow.rb @@ -391,7 +391,6 @@ def test_mechanical_ventilation_cfis_with_supplemental_fan # Get HPXML values vent_fan = hpxml_bldg.ventilation_fans.find { |f| f.used_for_whole_building_ventilation } vent_fan_cfm = vent_fan.oa_unit_flow_rate - vent_fan_power = vent_fan.fan_power vent_fan_mins = vent_fan.hours_in_operation / 24.0 * 60.0 suppl_vent_fan_cfm = vent_fan.cfis_supplemental_fan.oa_unit_flow_rate suppl_vent_fan_power = vent_fan.cfis_supplemental_fan.fan_power @@ -402,7 +401,6 @@ def test_mechanical_ventilation_cfis_with_supplemental_fan assert_in_epsilon(suppl_vent_fan_cfm, UnitConversions.convert(program_values['cfis_suppl_Q_oa'].sum, 'm^3/s', 'cfm'), 0.01) assert_in_epsilon(0.0, UnitConversions.convert(program_values['QWHV_sup'].sum, 'm^3/s', 'cfm'), 0.01) assert_in_epsilon(0.0, UnitConversions.convert(program_values['QWHV_exh'].sum, 'm^3/s', 'cfm'), 0.01) - assert_in_epsilon(vent_fan_power, program_values['cfis_fan_w'].sum, 0.01) assert_in_epsilon(suppl_vent_fan_power, program_values['cfis_suppl_fan_w'].sum, 0.01) assert_in_epsilon(vent_fan_mins, program_values['cfis_t_min_hr_open'].sum, 0.01) assert_in_epsilon(0.0, UnitConversions.convert(program_values['Qrange'].sum, 'm^3/s', 'cfm'), 0.01) diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence.xml index 9dd9aac927..c0633959a3 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence.xml @@ -1306,6 +1306,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-1.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-1.xml index 4d57068777..355b605e97 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-1.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-1.xml @@ -1306,6 +1306,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-12.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-12.xml index fdf7302d15..9dc1ef8c93 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-12.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-12.xml @@ -1306,6 +1306,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-13.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-13.xml index 9e1ba4eabe..d423bd675d 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-13.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-13.xml @@ -1307,6 +1307,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-15.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-15.xml index 9c6a3e243f..a92350bd64 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-15.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-15.xml @@ -1306,6 +1306,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-16.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-16.xml index ad001b5cac..64b20c3ea2 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-16.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-16.xml @@ -968,6 +968,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-17.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-17.xml index 0c73e57214..828781c72f 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-17.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-17.xml @@ -1306,6 +1306,7 @@ 300.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-2.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-2.xml index 7713ab3044..6cd62aa2b6 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-2.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-2.xml @@ -1306,6 +1306,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-22.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-22.xml index 01b53ef926..5f0b985cd6 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-22.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-22.xml @@ -1306,6 +1306,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-23.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-23.xml index ec5d672913..d30269fc6e 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-23.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-23.xml @@ -1110,6 +1110,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-3.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-3.xml index 514ee7f1ca..371378ce3c 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-3.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-3.xml @@ -1306,6 +1306,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-5.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-5.xml index 1e026ef373..b3895a25f4 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-5.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-5.xml @@ -1231,6 +1231,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-6.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-6.xml index 612ef36fb6..8c0fe25acf 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-6.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-6.xml @@ -1298,6 +1298,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-7.xml b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-7.xml index 274ac51f6e..537333d882 100644 --- a/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-7.xml +++ b/workflow/tests/ACCA_Examples/Bob_Ross_Residence_3-7.xml @@ -1306,6 +1306,7 @@ 150.0 8.0 true + 300.0 diff --git a/workflow/tests/ACCA_Examples/Walker_Residence.xml b/workflow/tests/ACCA_Examples/Walker_Residence.xml index 90e277d61c..76d0be3259 100644 --- a/workflow/tests/ACCA_Examples/Walker_Residence.xml +++ b/workflow/tests/ACCA_Examples/Walker_Residence.xml @@ -1033,6 +1033,7 @@ 150.0 8.0 true + 300.0 From e4fbc89a97ef03553d478acbab0029aa9d396bc1 Mon Sep 17 00:00:00 2001 From: Scott Horowitz Date: Thu, 29 Aug 2024 15:34:11 -0600 Subject: [PATCH 4/4] Update expected simulation results --- workflow/tests/util.rb | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/workflow/tests/util.rb b/workflow/tests/util.rb index 20a6f12b1c..ed85e42042 100644 --- a/workflow/tests/util.rb +++ b/workflow/tests/util.rb @@ -891,30 +891,31 @@ def _verify_outputs(rundir, hpxml_path, results, hpxml, unit_multiplier) assert_equal(hpxml_bldg.total_fraction_cool_load_served > 0, clg_energy > 0) # Mechanical Ventilation - whole_vent_fans = hpxml_bldg.ventilation_fans.select { |vent_mech| vent_mech.used_for_whole_building_ventilation && !vent_mech.is_cfis_supplemental_fan } - local_vent_fans = hpxml_bldg.ventilation_fans.select { |vent_mech| vent_mech.used_for_local_ventilation } - fan_cfis_with_addl_runtime = whole_vent_fans.select { |vent_mech| vent_mech.fan_type == HPXML::MechVentTypeCFIS && vent_mech.cfis_addtl_runtime_operating_mode != HPXML::CFISModeNone } - fan_sup = whole_vent_fans.select { |vent_mech| vent_mech.fan_type == HPXML::MechVentTypeSupply } - fan_exh = whole_vent_fans.select { |vent_mech| vent_mech.fan_type == HPXML::MechVentTypeExhaust } - fan_bal = whole_vent_fans.select { |vent_mech| [HPXML::MechVentTypeBalanced, HPXML::MechVentTypeERV, HPXML::MechVentTypeHRV].include?(vent_mech.fan_type) } - vent_fan_kitchen = local_vent_fans.select { |vent_mech| vent_mech.fan_location == HPXML::LocationKitchen } - vent_fan_bath = local_vent_fans.select { |vent_mech| vent_mech.fan_location == HPXML::LocationBath } + whole_vent_fans = hpxml_bldg.ventilation_fans.select { |f| f.used_for_whole_building_ventilation && !f.is_cfis_supplemental_fan } + local_vent_fans = hpxml_bldg.ventilation_fans.select { |f| f.used_for_local_ventilation } + fan_cfis = whole_vent_fans.select { |f| f.fan_type == HPXML::MechVentTypeCFIS && f.cfis_addtl_runtime_operating_mode != HPXML::CFISModeNone } + fan_sup = whole_vent_fans.select { |f| f.fan_type == HPXML::MechVentTypeSupply } + fan_exh = whole_vent_fans.select { |f| f.fan_type == HPXML::MechVentTypeExhaust } + fan_bal = whole_vent_fans.select { |f| [HPXML::MechVentTypeBalanced, HPXML::MechVentTypeERV, HPXML::MechVentTypeHRV].include?(f.fan_type) } + vent_fan_kitchen = local_vent_fans.select { |f| f.fan_location == HPXML::LocationKitchen } + vent_fan_bath = local_vent_fans.select { |f| f.fan_location == HPXML::LocationBath } mv_energy = UnitConversions.convert(results['End Use: Electricity: Mech Vent (MBtu)'], 'MBtu', 'GJ') - if not (fan_cfis_with_addl_runtime + fan_sup + fan_exh + fan_bal + vent_fan_kitchen + vent_fan_bath).empty? - if not fan_cfis_with_addl_runtime.empty? + if not (fan_cfis + fan_sup + fan_exh + fan_bal + vent_fan_kitchen + vent_fan_bath).empty? + if not fan_cfis.empty? if (fan_sup + fan_exh + fan_bal + vent_fan_kitchen + vent_fan_bath).empty? # CFIS only, check for positive mech vent energy that is less than the energy if it had run 24/7 - fan_gj = fan_cfis_with_addl_runtime.map { |vent_mech| UnitConversions.convert(vent_mech.unit_fan_power * vent_mech.hours_in_operation * 365.0, 'Wh', 'GJ') }.sum(0.0) + max_fan_gj = fan_cfis.select { |f| f.cfis_addtl_runtime_operating_mode == HPXML::CFISModeAirHandler }.map { |f| UnitConversions.convert(f.unit_fan_power * f.hours_in_operation * 365.0, 'Wh', 'GJ') }.sum(0.0) + max_fan_gj += fan_cfis.select { |f| f.cfis_addtl_runtime_operating_mode == HPXML::CFISModeSupplementalFan }.map { |f| UnitConversions.convert(f.cfis_supplemental_fan.unit_fan_power * (f.average_unit_flow_rate / f.cfis_supplemental_fan.oa_unit_flow_rate * 24) * 365.0, 'Wh', 'GJ') }.sum(0.0) assert_operator(mv_energy, :>, 0) - assert_operator(mv_energy, :<, fan_gj) + assert_operator(mv_energy, :<, max_fan_gj) end else # Supply, exhaust, ERV, HRV, etc., check for appropriate mech vent energy fan_gj = 0 - fan_gj += (fan_sup + fan_exh + fan_bal).map { |vent_mech| UnitConversions.convert(vent_mech.unit_fan_power * vent_mech.hours_in_operation * 365.0, 'Wh', 'GJ') }.sum(0.0) - fan_gj += vent_fan_kitchen.map { |vent_kitchen| UnitConversions.convert(vent_kitchen.unit_fan_power * vent_kitchen.hours_in_operation * vent_kitchen.count * 365.0, 'Wh', 'GJ') }.sum(0.0) - fan_gj += vent_fan_bath.map { |vent_bath| UnitConversions.convert(vent_bath.unit_fan_power * vent_bath.hours_in_operation * vent_bath.count * 365.0, 'Wh', 'GJ') }.sum(0.0) + fan_gj += (fan_sup + fan_exh + fan_bal).map { |f| UnitConversions.convert(f.unit_fan_power * f.hours_in_operation * 365.0, 'Wh', 'GJ') }.sum(0.0) + fan_gj += vent_fan_kitchen.map { |f| UnitConversions.convert(f.unit_fan_power * f.hours_in_operation * f.count * 365.0, 'Wh', 'GJ') }.sum(0.0) + fan_gj += vent_fan_bath.map { |f| UnitConversions.convert(f.unit_fan_power * f.hours_in_operation * f.count * 365.0, 'Wh', 'GJ') }.sum(0.0) # Maximum error that can be caused by rounding assert_in_delta(mv_energy, fan_gj, 0.006) end