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

CFIS cleanup #1816

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
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
18 changes: 9 additions & 9 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>3b678540-7b41-4cda-8eb9-a829bb0c5fe4</version_id>
<version_modified>2024-09-06T17:17:54Z</version_modified>
<version_id>8536783b-f268-4b67-93c6-0333cb254a49</version_id>
<version_modified>2024-09-06T21:10:53Z</version_modified>
<xml_checksum>D8922A73</xml_checksum>
<class_name>HPXMLtoOpenStudio</class_name>
<display_name>HPXML to OpenStudio Translator</display_name>
Expand Down Expand Up @@ -189,7 +189,7 @@
<filename>airflow.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>8D4E35DF</checksum>
<checksum>D0A17518</checksum>
</file>
<file>
<filename>battery.rb</filename>
Expand Down Expand Up @@ -357,13 +357,13 @@
<filename>hpxml.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>C2276348</checksum>
<checksum>FA21CFD4</checksum>
</file>
<file>
<filename>hpxml_defaults.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>92BB7113</checksum>
<checksum>694BB619</checksum>
</file>
<file>
<filename>hpxml_schema/HPXML.xsd</filename>
Expand All @@ -381,7 +381,7 @@
<filename>hpxml_schematron/EPvalidator.xml</filename>
<filetype>xml</filetype>
<usage_type>resource</usage_type>
<checksum>B4BB56DE</checksum>
<checksum>AEC0D551</checksum>
</file>
<file>
<filename>hpxml_schematron/iso-schematron.xsd</filename>
Expand Down Expand Up @@ -645,7 +645,7 @@
<filename>test_airflow.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>3A5212A2</checksum>
<checksum>18AC621F</checksum>
</file>
<file>
<filename>test_battery.rb</filename>
Expand All @@ -657,7 +657,7 @@
<filename>test_defaults.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>736CBC0A</checksum>
<checksum>489155C2</checksum>
</file>
<file>
<filename>test_enclosure.rb</filename>
Expand Down Expand Up @@ -729,7 +729,7 @@
<filename>test_validation.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>A0D2EEB9</checksum>
<checksum>1816D123</checksum>
</file>
<file>
<filename>test_water_heater.rb</filename>
Expand Down
2 changes: 1 addition & 1 deletion HPXMLtoOpenStudio/resources/airflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1860,7 +1860,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
Expand All @@ -1882,6 +1881,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
Expand Down
5 changes: 5 additions & 0 deletions HPXMLtoOpenStudio/resources/hpxml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8162,6 +8162,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

Expand Down
11 changes: 6 additions & 5 deletions HPXMLtoOpenStudio/resources/hpxml_defaults.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2613,20 +2613,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?
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
Expand Down
27 changes: 19 additions & 8 deletions HPXMLtoOpenStudio/resources/hpxml_schematron/EPvalidator.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2006,30 +2006,41 @@
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Systems/h:MechanicalVentilation/h:VentilationFans/h:VentilationFan[h:UsedForWholeBuildingVentilation="true" and h:FanType="central fan integrated supply"]'>
<sch:assert role='ERROR' test='count(h:IsSharedSystem[text()="true"]) = 0'>Expected 0 element(s) for xpath: IsSharedSystem[text()="true"]</sch:assert>
<sch:assert role='ERROR' test='count(h:CFISControls/h:AdditionalRuntimeOperatingMode) &lt;= 1'>Expected 0 or 1 element(s) for xpath: CFISControls/AdditionalRuntimeOperatingMode</sch:assert>
<sch:assert role='ERROR' test='h:CFISControls/h:AdditionalRuntimeOperatingMode[text()="air handler fan" or text()="supplemental fan" or text()="none"] or not(h:CFISControls/h:AdditionalRuntimeOperatingMode)'>Expected CFISControls/AdditionalRuntimeOperatingMode to be 'air handler fan' or 'supplemental fan' or 'none'</sch:assert> <!-- See [MechanicalVentilationType=CFISWithSupplementalFan] -->
<sch:assert role='ERROR' test='h:CFISControls/h:AdditionalRuntimeOperatingMode[text()="air handler fan" or text()="supplemental fan" or text()="none"] or not(h:CFISControls/h:AdditionalRuntimeOperatingMode)'>Expected CFISControls/AdditionalRuntimeOperatingMode to be 'air handler fan' or 'supplemental fan' or 'none'</sch:assert> <!-- See [CFISAdditionalRuntimeMode=AirHandlerFan] or [CFISAdditionalRuntimeMode=SupplementalFan] or [CFISAdditionalRuntimeMode=None] -->
<sch:assert role='ERROR' test='count(h:RatedFlowRate) + count(h:CalculatedFlowRate) + count(h:TestedFlowRate) + count(h:DeliveredVentilation) &gt;= 0'>Expected 0 or more element(s) for xpath: RatedFlowRate | CalculatedFlowRate | TestedFlowRate | DeliveredVentilation</sch:assert>
<sch:assert role='ERROR' test='count(h:HoursInOperation) &lt;= 1'>Expected 0 or 1 element(s) for xpath: HoursInOperation</sch:assert>
<sch:assert role='ERROR' test='count(h:TotalRecoveryEfficiency) + count(h:AdjustedTotalRecoveryEfficiency) = 0'>Expected 0 element(s) for xpath: TotalRecoveryEfficiency | AdjustedTotalRecoveryEfficiency</sch:assert>
<sch:assert role='ERROR' test='count(h:SensibleRecoveryEfficiency) + count(h:AdjustedSensibleRecoveryEfficiency) = 0'>Expected 0 element(s) for xpath: SensibleRecoveryEfficiency | AdjustedSensibleRecoveryEfficiency</sch:assert>
<sch:assert role='ERROR' test='count(h:FanPower) &lt;= 1'>Expected 0 or 1 element(s) for xpath: FanPower</sch:assert>
<sch:assert role='ERROR' test='count(h:AttachedToHVACDistributionSystem) = 1'>Expected 1 element(s) for xpath: AttachedToHVACDistributionSystem</sch:assert>
</sch:rule>
</sch:pattern>

<sch:pattern>
<sch:title>[CFISAdditionalRuntimeMode=AirHandlerFan]</sch:title>
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Systems/h:MechanicalVentilation/h:VentilationFans/h:VentilationFan[h:UsedForWholeBuildingVentilation="true" and h:FanType="central fan integrated supply" and h:CFISControls/h:AdditionalRuntimeOperatingMode="air handler fan"]'>
<sch:assert role='ERROR' test='count(h:CFISControls/h:SupplementalFan) = 0'>Expected 0 element(s) for xpath: CFISControls/SupplementalFan</sch:assert>
<sch:assert role='ERROR' test='count(h:FanPower) &lt;= 1'>Expected 0 or 1 element(s) for xpath: FanPower</sch:assert>
<sch:assert role='ERROR' test='count(h:extension/h:VentilationOnlyModeAirflowFraction) &lt;= 1'>Expected 0 or 1 element(s) for xpath: extension/VentilationOnlyModeAirflowFraction</sch:assert>
<sch:assert role='ERROR' test='number(h:extension/h:VentilationOnlyModeAirflowFraction) &gt;= 0 or not(h:extension/h:VentilationOnlyModeAirflowFraction)'>Expected extension/VentilationOnlyModeAirflowFraction to be greater than or equal to 0</sch:assert>
<sch:assert role='ERROR' test='number(h:extension/h:VentilationOnlyModeAirflowFraction) &lt;= 1 or not(h:extension/h:VentilationOnlyModeAirflowFraction)'>Expected extension/VentilationOnlyModeAirflowFraction to be less than or equal to 1</sch:assert>
</sch:rule>
</sch:pattern>

<sch:pattern>
<sch:title>[MechanicalVentilationType=CFISWithSupplementalFan]</sch:title>
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Systems/h:MechanicalVentilation/h:VentilationFans/h:VentilationFan[h:UsedForWholeBuildingVentilation="true" and h:FanType="central fan integrated supply"]/h:CFISControls[h:AdditionalRuntimeOperatingMode="supplemental fan"]'>
<sch:assert role='ERROR' test='count(h:SupplementalFan) = 1'>Expected 1 element(s) for xpath: SupplementalFan</sch:assert>
<sch:title>[CFISAdditionalRuntimeMode=SupplementalFan]</sch:title>
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Systems/h:MechanicalVentilation/h:VentilationFans/h:VentilationFan[h:UsedForWholeBuildingVentilation="true" and h:FanType="central fan integrated supply" and h:CFISControls/h:AdditionalRuntimeOperatingMode="supplemental fan"]'>
<sch:assert role='ERROR' test='count(h:CFISControls/h:SupplementalFan) = 1'>Expected 1 element(s) for xpath: CFISControls/SupplementalFan</sch:assert>
<sch:assert role='ERROR' test='count(h:FanPower) = 0'>Expected 0 element(s) for xpath: FanPower</sch:assert>
<sch:assert role='ERROR' test='count(h:extension/h:VentilationOnlyModeAirflowFraction) = 0'>Expected 0 element(s) for xpath: extension/VentilationOnlyModeAirflowFraction</sch:assert>
</sch:rule>
</sch:pattern>

<sch:pattern>
<sch:title>[MechanicalVentilationType=CFISWithoutSupplementalFan]</sch:title>
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Systems/h:MechanicalVentilation/h:VentilationFans/h:VentilationFan[h:UsedForWholeBuildingVentilation="true" and h:FanType="central fan integrated supply"]/h:CFISControls[h:AdditionalRuntimeOperatingMode!="supplemental fan"]'>
<sch:assert role='ERROR' test='count(h:SupplementalFan) = 0'>Expected 0 element(s) for xpath: SupplementalFan</sch:assert>
<sch:title>[CFISAdditionalRuntimeMode=None]</sch:title>
<sch:rule context='/h:HPXML/h:Building/h:BuildingDetails/h:Systems/h:MechanicalVentilation/h:VentilationFans/h:VentilationFan[h:UsedForWholeBuildingVentilation="true" and h:FanType="central fan integrated supply" and h:CFISControls/h:AdditionalRuntimeOperatingMode="none"]'>
<sch:assert role='ERROR' test='count(h:CFISControls/h:SupplementalFan) = 0'>Expected 0 element(s) for xpath: CFISControls/SupplementalFan</sch:assert>
<sch:assert role='ERROR' test='count(h:FanPower) = 0'>Expected 0 element(s) for xpath: FanPower</sch:assert>
<sch:assert role='ERROR' test='count(h:extension/h:VentilationOnlyModeAirflowFraction) = 0'>Expected 0 element(s) for xpath: extension/VentilationOnlyModeAirflowFraction</sch:assert>
</sch:rule>
</sch:pattern>

Expand Down
4 changes: 1 addition & 3 deletions HPXMLtoOpenStudio/tests/test_airflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,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
Expand All @@ -412,7 +411,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)
Expand Down Expand Up @@ -498,7 +496,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
Expand Down
43 changes: 30 additions & 13 deletions HPXMLtoOpenStudio/tests/test_defaults.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2842,23 +2842,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
Expand All @@ -2878,7 +2891,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')
Expand Down Expand Up @@ -5258,7 +5271,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)
Expand Down
Loading