Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
5fdc4bb
Allow natural ventilation year-round (heating and cooling seasons) pe…
shorowit Jan 22, 2026
81f0053
More progress.
shorowit Jan 22, 2026
12a18b9
Add seasons input; default to year-round.
shorowit Jan 22, 2026
8d98706
Update unit tests.
shorowit Jan 22, 2026
f928d38
Simplify logic, update component loads program.
shorowit Jan 23, 2026
e6fc7e7
Update test.
shorowit Jan 23, 2026
40e77f9
Latest results.
Jan 23, 2026
1503ad3
Merge branch 'master' of https://github.com/NatLabRockies/OpenStudio-…
shorowit Jan 28, 2026
e8cc85d
Move natural ventilation inputs into a NaturalVentilationControl pare…
shorowit Feb 6, 2026
400f72d
Merge branch 'master' of https://github.com/NatLabRockies/OpenStudio-…
shorowit Feb 6, 2026
6c72474
Update HPXML
shorowit Feb 6, 2026
eb43f99
Expose input for open fraction of operable window area.
shorowit Feb 6, 2026
bded69b
Latest results.
Feb 6, 2026
331c060
Bump up value in example
shorowit Feb 9, 2026
188ff11
Forgot to update test.
shorowit Feb 9, 2026
1fd8955
Merge branch 'master' of https://github.com/NatLabRockies/OpenStudio-…
shorowit Feb 11, 2026
69295eb
Latest results.
Feb 11, 2026
efbd37f
Merge branch 'master' of https://github.com/NatLabRockies/OpenStudio-…
shorowit Mar 16, 2026
03ba00b
Some cleanup.
shorowit Mar 16, 2026
d6e69fd
Update tests.
shorowit Mar 16, 2026
b58d658
Relax tolerance; resilience metric can be very sensitive to small cha…
shorowit Mar 16, 2026
00cce79
Latest results.
Mar 16, 2026
dcc1013
Merge branch 'master' of https://github.com/NatLabRockies/OpenStudio-…
shorowit Mar 30, 2026
b420a3d
Minor cleanup [ci skip]
shorowit Mar 30, 2026
fb833e2
Small doc sclarification [ci skip]
shorowit Mar 30, 2026
2f7c939
Update component load logic.
shorowit Mar 30, 2026
37a6824
Latest results.
Mar 30, 2026
b564a4b
Separate WHF logic (cooling only, no HR limit) from NV logic.
shorowit Mar 30, 2026
fc68559
Merge branch 'year_round_nat_vent' of https://github.com/NatLabRockie…
shorowit Mar 30, 2026
52062eb
Make logic easier to understand.
shorowit Mar 30, 2026
b2a0eb8
Don't constrain WHF based on cooling season.
shorowit Mar 30, 2026
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
2 changes: 1 addition & 1 deletion BuildResidentialHPXML/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ The amount of natural ventilation from occupants opening operable windows when o

- **Required:** ``false``

- **Choices:** <br/> - `None`<br/> - `33% Operable Windows`<br/> - `50% Operable Windows`<br/> - `67% Operable Windows`<br/> - `100% Operable Windows`<br/> - `Detailed Example: 67% Operable Windows, 7 Days/Week`
- **Choices:** <br/> - `None`<br/> - `33% Operable Windows`<br/> - `50% Operable Windows`<br/> - `67% Operable Windows`<br/> - `100% Operable Windows`<br/> - `Detailed Example: 67% Operable Windows, 20% Open, 3 Days/Week, Cooling Only`


- **Default:** `67% Operable Windows`
Expand Down
2 changes: 2 additions & 0 deletions BuildResidentialHPXML/measure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1569,7 +1569,9 @@ def set_building_header(hpxml_bldg, args)
end
hpxml_bldg.header.heat_pump_sizing_methodology = args[:hvac_heat_pump_capacity_autosizing_methodology]
hpxml_bldg.header.heat_pump_backup_sizing_methodology = args[:hvac_heat_pump_backup_capacity_autosizing_methodology]
hpxml_bldg.header.natvent_seasons = args[:enclosure_window_natural_ventilation_seasons]
hpxml_bldg.header.natvent_days_per_week = args[:enclosure_window_natural_ventilation_availability]
hpxml_bldg.header.natvent_open_frac_of_operable_area = args[:enclosure_window_natural_ventilation_open_fraction]

hvac_incr = args[:advanced_feature_hvac_allow_increased_fixed_capacities]
hvac_incr = args[:advanced_feature_2_hvac_allow_increased_fixed_capacities] if hvac_incr.nil?
Expand Down
14 changes: 7 additions & 7 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>d78d122b-6e59-4fde-af8a-1708240ade46</version_id>
<version_modified>2026-03-26T20:59:07Z</version_modified>
<version_id>8443592b-8b44-476b-8036-4eb0651a1353</version_id>
<version_modified>2026-03-30T15:02:42Z</version_modified>
<xml_checksum>2C38F48B</xml_checksum>
<class_name>BuildResidentialHPXML</class_name>
<display_name>HPXML Builder</display_name>
Expand Down Expand Up @@ -2873,8 +2873,8 @@
<display_name>100% Operable Windows</display_name>
</choice>
<choice>
<value>Detailed Example: 67% Operable Windows, 7 Days/Week</value>
<display_name>Detailed Example: 67% Operable Windows, 7 Days/Week</display_name>
<value>Detailed Example: 67% Operable Windows, 20% Open, 3 Days/Week, Cooling Only</value>
<display_name>Detailed Example: 67% Operable Windows, 20% Open, 3 Days/Week, Cooling Only</display_name>
</choice>
</choices>
</argument>
Expand Down Expand Up @@ -11413,7 +11413,7 @@
<filename>README.md</filename>
<filetype>md</filetype>
<usage_type>readme</usage_type>
<checksum>75446FA4</checksum>
<checksum>7A70433D</checksum>
</file>
<file>
<filename>README.md.erb</filename>
Expand All @@ -11430,7 +11430,7 @@
<filename>measure.rb</filename>
<filetype>rb</filetype>
<usage_type>script</usage_type>
<checksum>73832BEA</checksum>
<checksum>CD3517B8</checksum>
</file>
<file>
<filename>constants.rb</filename>
Expand Down Expand Up @@ -11706,7 +11706,7 @@
<filename>options/enclosure_window_natural_ventilation.tsv</filename>
<filetype>tsv</filetype>
<usage_type>resource</usage_type>
<checksum>391C269D</checksum>
<checksum>A3F8951E</checksum>
</file>
<file>
<filename>options/enclosure_window_storm.tsv</filename>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
Option Name Fraction Operable [frac] Availability [days/week]
None 0
33% Operable Windows 0.33
50% Operable Windows 0.5
67% Operable Windows 0.67
100% Operable Windows 1
"Detailed Example: 67% Operable Windows, 7 Days/Week" 0.67 7

"# Fraction Operable: Total window area for operable windows divided by total window area. The total open window area for natural ventilation is calculated using A) the operable fraction, B) the assumption that only some of the area of operable windows can be open, and C) the assumption that only some of that openable area is actually opened by occupants whenever outdoor conditions are favorable."
# Availability: How many days per week windows can be opened by occupants.
Option Name Fraction Operable [frac] Open Fraction [frac] Availability [days/week] Seasons
None 0
33% Operable Windows 0.33
50% Operable Windows 0.5
67% Operable Windows 0.67
100% Operable Windows 1
"Detailed Example: 67% Operable Windows, 20% Open, 3 Days/Week, Cooling Only" 0.67 0.2 3 cooling

"# Fraction Operable: Total window area for operable windows divided by total window area. The total open window area for natural ventilation is calculated using A) the operable fraction, B) the assumption that only some of the area of operable windows can be open, and C) the assumption that only some of that openable area is actually opened by occupants."
# Open Fraction: Fraction of operable window area that is open during ventilation.
# Availability: How many days per week windows can be opened by occupants.
# Seasons: When during the year occupants open windows.
4 changes: 4 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ __New Features__
- HVAC updates:
- Dual-fuel heat pumps with switchover temperatures > 25F are now autosized based on 25F to allow some additional heating capacity buffer.
- Improves handling of duct leakage specified using cfm25/cfm50.
- Natural ventilation updates:
- **Breaking change**: Replaces `NaturalVentilationAvailabilityDaysperWeek` with `NaturalVentilationControl/DaysperWeek`; now defaults to 7 instead of 3 to align with ANSI 301.
- Adds `NaturalVentilationControl/Seasons` ("year-round", "cooling", or "heating") to control seasonal natural ventilation availability; now defaults to year-round instead of cooling.
- Adds `NaturalVentilationControl/OpenFractionofOperableArea` to control the fraction of operable window area that is open during natural ventilation periods.
- Allows "other" for `SoilType`; adds variation to dry/wet soil conductivity and diffusivity values for unknown/other/loam soil types.
- Output updates:
- **Breaking change**: Annual peak load outputs for heating and cooling now use units of Btu/h instead of kBtu/h for consistency with other outputs.
Expand Down
22 changes: 11 additions & 11 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>327faec4-f087-4b81-8f98-270832317762</version_id>
<version_modified>2026-03-26T20:59:14Z</version_modified>
<version_id>747e333b-6316-485c-9007-b3d4c6783524</version_id>
<version_modified>2026-03-30T17:00:59Z</version_modified>
<xml_checksum>D8922A73</xml_checksum>
<class_name>HPXMLtoOpenStudio</class_name>
<display_name>HPXML to OpenStudio Translator</display_name>
Expand Down Expand Up @@ -217,7 +217,7 @@
<filename>airflow.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>2F17E22A</checksum>
<checksum>B434D374</checksum>
</file>
<file>
<filename>battery.rb</filename>
Expand Down Expand Up @@ -367,7 +367,7 @@
<filename>defaults.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>F91B9101</checksum>
<checksum>6EEE1C65</checksum>
</file>
<file>
<filename>electric_panel.rb</filename>
Expand Down Expand Up @@ -403,7 +403,7 @@
<filename>hpxml.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>BF5902DA</checksum>
<checksum>EBEAC4AE</checksum>
</file>
<file>
<filename>hpxml_schema/HPXML.xsd</filename>
Expand All @@ -421,7 +421,7 @@
<filename>hpxml_schematron/EPvalidator.sch</filename>
<filetype>sch</filetype>
<usage_type>resource</usage_type>
<checksum>9B5934A8</checksum>
<checksum>5C25CBD0</checksum>
</file>
<file>
<filename>hpxml_schematron/iso-schematron.xsd</filename>
Expand Down Expand Up @@ -499,7 +499,7 @@
<filename>output.rb</filename>
<filetype>rb</filetype>
<usage_type>resource</usage_type>
<checksum>7F8E008D</checksum>
<checksum>CCB6EE33</checksum>
</file>
<file>
<filename>psychrometrics.rb</filename>
Expand Down Expand Up @@ -739,7 +739,7 @@
<filename>test_airflow.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>3D655417</checksum>
<checksum>EF1881C2</checksum>
</file>
<file>
<filename>test_battery.rb</filename>
Expand All @@ -751,7 +751,7 @@
<filename>test_defaults.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>989C355A</checksum>
<checksum>AE52447F</checksum>
</file>
<file>
<filename>test_electric_panel.rb</filename>
Expand Down Expand Up @@ -817,7 +817,7 @@
<filename>test_schedules.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>D5468D70</checksum>
<checksum>18B8FADA</checksum>
</file>
<file>
<filename>test_simcontrols.rb</filename>
Expand All @@ -829,7 +829,7 @@
<filename>test_validation.rb</filename>
<filetype>rb</filetype>
<usage_type>test</usage_type>
<checksum>5146716A</checksum>
<checksum>90504282</checksum>
</file>
<file>
<filename>test_vehicle.rb</filename>
Expand Down
106 changes: 64 additions & 42 deletions HPXMLtoOpenStudio/resources/airflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,10 @@ def self.create_sensors(model, weather, spaces, hpxml_bldg)
key_name: conditioned_zone.name
)

# Create cooling season schedule sensor (applies only to natural ventilation, not HVAC equipment).
# Uses BAHSP cooling season, not user-specified cooling season (which may be, e.g., year-round).
_, default_cooling_months = HVAC.get_building_america_hvac_seasons(weather, hpxml_bldg.latitude)
clg_season_sch = MonthWeekdayWeekendSchedule.new(model, 'cooling season schedule', Array.new(24, 1), Array.new(24, 1), default_cooling_months, EPlus::ScheduleTypeLimitsFraction)
# Create cooling season schedule sensors (applies only to natural ventilation, not HVAC equipment).
# Uses BAHSP cooling season, not user-specified cooling season (which is typically year-round).
_, bahsp_cooling_months = HVAC.get_building_america_hvac_seasons(weather, hpxml_bldg.latitude)
clg_season_sch = MonthWeekdayWeekendSchedule.new(model, 'cooling season schedule', Array.new(24, 1), Array.new(24, 1), bahsp_cooling_months, EPlus::ScheduleTypeLimitsFraction)
sensors[:clg_ssn] = Model.add_ems_sensor(
model,
name: 'cool_season',
Expand Down Expand Up @@ -395,7 +395,6 @@ def self.apply_natural_ventilation_and_whole_house_fan(runner, model, spaces, hp

# Natural Ventilation availability schedule and sensor
nv_avail_sch = create_sched_from_num_days_per_week(model, Constants::ObjectTypeNaturalVentilation, hpxml_bldg.header.natvent_days_per_week, hpxml_header.unavailable_periods)

nv_avail_sensor = Model.add_ems_sensor(
model,
name: "#{Constants::ObjectTypeNaturalVentilation} s",
Expand Down Expand Up @@ -507,9 +506,8 @@ def self.apply_natural_ventilation_and_whole_house_fan(runner, model, spaces, hp
)
end

# Assume A) 50% of the area of an operable window can be open, and B) 20% of openable window area is actually open
window_area = hpxml_bldg.windows.map { |w| w.area }.sum(0.0)
open_window_area = window_area * hpxml_bldg.additional_properties.initial_frac_windows_operable * 0.5 * 0.2
open_window_area = window_area * hpxml_bldg.additional_properties.initial_frac_windows_operable * hpxml_bldg.header.natvent_open_frac_of_operable_area

area = 0.6 * open_window_area # ft^2, for Sherman-Grimsrud (ASHRAE Basic Model)
max_rate = 20.0 # Air Changes per hour
Expand All @@ -535,7 +533,7 @@ def self.apply_natural_ventilation_and_whole_house_fan(runner, model, spaces, hp
vent_program.addLine("Set MaxHR = #{max_oa_hr}")
if not thermostat.nil?
# Home has HVAC system (though setpoints may be defaulted); use the average of heating/cooling setpoints to minimize incurring additional heating energy.
vent_program.addLine("Set Tnvsp = (#{htg_sp_sensor.name} + #{clg_sp_sensor.name}) / 2")
vent_program.addLine("Set Tmidsp = (#{htg_sp_sensor.name} + #{clg_sp_sensor.name}) / 2")
else
# No HVAC system; use the average of defaulted heating/cooling setpoints.
htg_weekday_setpoints, htg_weekend_setpoints = Defaults.get_heating_setpoint(HPXML::HVACControlTypeManual, hpxml_header.eri_calculation_versions[0])
Expand All @@ -550,56 +548,80 @@ def self.apply_natural_ventilation_and_whole_house_fan(runner, model, spaces, hp
else
fail 'Unexpected cooling setpoints.'
end
vent_program.addLine("Set Tnvsp = (#{default_htg_sp} + #{default_clg_sp}) / 2")
vent_program.addLine("Set Tmidsp = (#{default_htg_sp} + #{default_clg_sp}) / 2")
end
vent_program.addLine("Set NVavailDayofWeek = #{nv_avail_sensor.name}")
if hpxml_bldg.header.natvent_seasons == HPXML::NatVentSeasonsYearRound
vent_program.addLine('Set NVavailSeasonHtg = 1')
vent_program.addLine('Set NVavailSeasonClg = 1')
elsif hpxml_bldg.header.natvent_seasons == HPXML::NatVentSeasonsCooling
vent_program.addLine("Set NVavailSeasonClg = #{sensors[:clg_ssn].name}")
vent_program.addLine('Set NVavailSeasonHtg = 0')
elsif hpxml_bldg.header.natvent_seasons == HPXML::NatVentSeasonsHeating
vent_program.addLine("Set NVavailSeasonHtg = 1 - #{sensors[:clg_ssn].name}")
vent_program.addLine('Set NVavailSeasonClg = 0')
end
vent_program.addLine("Set NVavail = #{nv_avail_sensor.name}")
vent_program.addLine("Set ClgSsnAvail = #{sensors[:clg_ssn].name}")
vent_program.addLine('Set Qnv = 0') # Init
vent_program.addLine('Set Qwhf = 0') # Init
vent_program.addLine("Set #{cond_to_zone_flow_rate_actuator.name} = 0") unless whf_zone.nil? # Init
vent_program.addLine("Set #{whf_elec_actuator.name} = 0") # Init
infil_constraints = 'If ((Wout < MaxHR) && (Tin > Tout) && (Tin > Tnvsp) && (ClgSsnAvail > 0))'

# Natural ventilation constraints
# From ANSI 301
# allow natural ventilation when the outdoor humidity ratio is less than 0.0115 lb_w/lb_da and either:
# A) outdoor temperature is below the indoor temperature and the indoor temperature is above the average of the heating and cooling setpoints, or
# B) outdoor temperature is above the indoor temperature and the indoor temperature is below the average of the heating and cooling setpoints
natvent_constraints = '(((Tout < Tin) && (Tin > Tmidsp) && (NVavailSeasonClg == 1)) || ((Tout > Tin) && (Tin < Tmidsp) && (NVavailSeasonHtg == 1)))'
if not clg_avail_sensor.nil?
# We are using the availability schedule, but we also constrain the window opening based on temperatures and humidity.
# We're assuming that if the HVAC is not available, you'd ignore the humidity constraints we normally put on window opening per the old HSP guidance (RH < 70% and w < 0.015).
# Without, the humidity constraints prevent the window from opening during the entire period even though the sensible cooling would have really helped.
infil_constraints += "|| ((Tin > Tout) && (Tin > Tnvsp) && (#{clg_avail_sensor.name} == 0))"
# Ignore the humidity constraint when space cooling is not available (e.g., power outage), in order to allow as much natural ventilation as possible
natvent_constraints += " && ((Wout < MaxHR) || (#{clg_avail_sensor.name} == 0))"
else
natvent_constraints += ' && (Wout < MaxHR)'
end
vent_program.addLine(infil_constraints)
vent_program.addLine(' Set WHF_Flow = 0')

# Whole-house fan constraints (cooling only)
whf_constraints = '(Tout < Tin) && (Tin > Tmidsp)'

vent_program.addLine('Set WHF_Flow = 0')
vent_fans[:whf].each do |vent_whf|
vent_program.addLine(" Set WHF_Flow = WHF_Flow + #{UnitConversions.convert(vent_whf.flow_rate, 'cfm', 'm^3/s')} * #{whf_avail_sensors[vent_whf.id].name}")
end
vent_program.addLine(' Set Adj = (Tin-Tnvsp)/(Tin-Tout)')
vent_program.addLine(' Set Adj = (@Min Adj 1)')
vent_program.addLine(' Set Adj = (@Max Adj 0)')
vent_program.addLine(' If (WHF_Flow > 0)') # If available, prioritize whole house fan
vent_program.addLine(' Set Qwhf = WHF_Flow*Adj')
vent_program.addLine(" Set #{cond_to_zone_flow_rate_actuator.name} = WHF_Flow*Adj") unless whf_zone.nil?
vent_program.addLine(' Set WHF_W = 0')
vent_program.addLine("Set WHF_Flow = WHF_Flow + #{UnitConversions.convert(vent_whf.flow_rate, 'cfm', 'm^3/s')} * #{whf_avail_sensors[vent_whf.id].name}")
end
vent_program.addLine('If Tin > Tout')
vent_program.addLine(' Set Adj = (Tin-Tmidsp)/(Tin-Tout)')
vent_program.addLine('ElseIf Tout > Tin')
vent_program.addLine(' Set Adj = (Tmidsp-Tin)/(Tout-Tin)')
vent_program.addLine('EndIf')
vent_program.addLine('Set Adj = (@Min Adj 1)')
vent_program.addLine('Set Adj = (@Max Adj 0)')

vent_program.addLine("If (WHF_Flow > 0) && #{whf_constraints}") # If available, prioritize whole house fan
vent_program.addLine(' Set Qwhf = WHF_Flow*Adj')
vent_program.addLine(" Set #{cond_to_zone_flow_rate_actuator.name} = WHF_Flow*Adj") unless whf_zone.nil?
vent_program.addLine(' Set WHF_W = 0')
if hpxml_bldg.building_occupancy.number_of_residents != 0 # If operational calculation w/ zero occupants, zero out whole house fan
vent_fans[:whf].each do |vent_whf|
vent_program.addLine(" Set WHF_W = WHF_W + #{vent_whf.fan_power} * #{whf_avail_sensors[vent_whf.id].name}")
vent_program.addLine(" Set WHF_W = WHF_W + #{vent_whf.fan_power} * #{whf_avail_sensors[vent_whf.id].name}")
end
end
vent_program.addLine(" Set #{whf_elec_actuator.name} = WHF_W*Adj")
vent_program.addLine(' ElseIf (NVavail > 0)') # Natural ventilation
vent_program.addLine(" Set #{whf_elec_actuator.name} = WHF_W*Adj")

vent_program.addLine("ElseIf (NVavailDayofWeek > 0) && #{natvent_constraints}") # Natural ventilation
if hpxml_bldg.building_occupancy.number_of_residents == 0
# Operational calculation w/ zero occupants, zero out natural ventilation
vent_program.addLine(' Set NVArea = 0')
vent_program.addLine(' Set NVArea = 0')
else
vent_program.addLine(" Set NVArea = #{UnitConversions.convert(area, 'ft^2', 'cm^2')}")
end
vent_program.addLine(" Set Cs = #{UnitConversions.convert(c_s, 'ft^2/(s^2*R)', 'L^2/(s^2*cm^4*K)')}")
vent_program.addLine(" Set Cw = #{c_w * 0.01}")
vent_program.addLine(' Set Tdiff = Tin-Tout')
vent_program.addLine(' Set dT = (@Abs Tdiff)')
vent_program.addLine(" Set Vwind = #{sensors[:v_wind].name}")
vent_program.addLine(' Set SGNV = NVArea*Adj*((((Cs*dT)+(Cw*(Vwind^2)))^0.5)/1000)')
vent_program.addLine(" Set MaxNV = #{UnitConversions.convert(max_flow_rate, 'cfm', 'm^3/s')}")
vent_program.addLine(' Set Qnv = (@Min SGNV MaxNV)')
vent_program.addLine(' EndIf')
vent_program.addLine(" Set NVArea = #{UnitConversions.convert(area, 'ft^2', 'cm^2')}")
end
vent_program.addLine(" Set Cs = #{UnitConversions.convert(c_s, 'ft^2/(s^2*R)', 'L^2/(s^2*cm^4*K)')}")
vent_program.addLine(" Set Cw = #{c_w * 0.01}")
vent_program.addLine(' Set Tdiff = Tin-Tout')
vent_program.addLine(' Set dT = (@Abs Tdiff)')
vent_program.addLine(" Set Vwind = #{sensors[:v_wind].name}")
vent_program.addLine(' Set SGNV = NVArea*Adj*((((Cs*dT)+(Cw*(Vwind^2)))^0.5)/1000)')
vent_program.addLine(" Set MaxNV = #{UnitConversions.convert(max_flow_rate, 'cfm', 'm^3/s')}")
vent_program.addLine(' Set Qnv = (@Min SGNV MaxNV)')
vent_program.addLine('EndIf')

vent_program.addLine("Set #{nv_flow_actuator.name} = Qnv")
vent_program.addLine("Set #{whf_flow_actuator.name} = Qwhf")

Expand Down
Loading
Loading