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

ASHRAE 62.1 Simplified Procedure #1112

Merged
merged 6 commits into from
Sep 14, 2021
Merged

Conversation

lymereJ
Copy link
Collaborator

@lymereJ lymereJ commented Jun 21, 2021

The proposed changes update the method to calculate the minimum damper position and system design outdoor air based on the ASHRAE 62.1 Simplified Procedure (as opposed to the method in Appendix A) as required by ASHRAE 90.1-2019. Additional information regarding the implementation are provided in Section B2.7 in the Energy Savings Analysis: ANSI/ASHRAE/IES Standard 90.1-2019 report.

The proposed changes also improve the existing method by letting EnergyPlus size the system outdoor air intake based on a minimum zone ventilation of 0.6 (not possible before OS 3.0, follow up on the issue identified in #776), and remove redundant code.

Note: It was noticed that the maximum air terminal air flow calculated from the sizing run could be different from the annual simulation run. The reason for that is that sizing runs are currently done without daylighting control, as they should, but autosizing calculation for the annual run are done with daylighting control because OS currently doesn't allow setting an availability schedule to daylighting control, see here.

Note 2: This PR is affected by NREL/OpenStudio#4436.

@lymereJ lymereJ added the 90.1-2016/9 Flag PR targeting code changes related to the 90.1-2016/9 update label Jun 21, 2021
@lymereJ lymereJ self-assigned this Jun 21, 2021
Comment on lines -4 to -24
# Apply multizone vav outdoor air method and
# adjust multizone VAV damper positions
# to achieve a system minimum ventilation effectiveness
# of 0.6 per PNNL. Hard-size the resulting min OA
# into the sizing:system object.
#
# return [Bool] returns true if successful, false if not
# @todo move building-type-specific code to Prototype classes
def air_loop_hvac_apply_multizone_vav_outdoor_air_sizing(air_loop_hvac)
# First time adjustment:
# Only applies to multi-zone vav systems
# exclusion: for Outpatient: (1) both AHU1 and AHU2 in 'DOE Ref Pre-1980' and 'DOE Ref 1980-2004'
# (2) AHU1 in 2004-2019
# TODO refactor: move building-type-specific code to Prototype classes
if air_loop_hvac_multizone_vav_system?(air_loop_hvac) && !(air_loop_hvac.name.to_s.include? 'Outpatient F1')
air_loop_hvac_adjust_minimum_vav_damper_positions(air_loop_hvac)
end

return true
end

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Remove redundant code.

Comment on lines 435 to 603
# on a per zone basis, the zone primary airflow is
# adjusted to removed the zone multiplier
v_pz /= zone.multiplier.to_f

# Set minimum damper position
air_loop_hvac_set_minimum_damper_position(zone, [0.01, [1.5 * v_oz / v_pz, 1.0].min].max.round(3))
end

# Occupant diversity (D): Ps / sum(Pz)
# Current value is based on school prototypes
# which are assumed to have the most diversity
occ_diver_d = 0.66

# From ASHRAE Std 62.1-2019 Section 6.2.5.3
if occ_diver_d < 0.6
e_v = 0.88 * occ_diver_d + 0.22
else
e_v = 0.75
end

# Total system outdoor intake flow rate
v_ot = v_ou / e_v
v_ot_cfm = OpenStudio.convert(v_ot, 'm^3/s', 'cfm').get

# Get maximum OA fraction schedule
oa_ctrl = air_loop_hvac.airLoopHVACOutdoorAirSystem.get.getControllerOutdoorAir
max_oa_frac_sch = oa_ctrl.maximumFractionofOutdoorAirSchedule

if !max_oa_frac_sch.is_initialized
max_oa_frac_sch = OpenStudio::Model::ScheduleConstant.new(air_loop_hvac.model)
max_oa_frac_sch.setName("#{air_loop_hvac.name}_MAX_OA_FRAC")
max_oa_frac_sch.setValue(1.0)
max_oa_frac_sch_type = 'Schedule:Constant'
oa_ctrl.setMaximumFractionofOutdoorAirSchedule(max_oa_frac_sch)
else
if max_oa_frac_sch.to_ScheduleRuleset.is_initialized
max_oa_frac_sch = max_oa_frac_sch.to_ScheduleRuleset.get
max_oa_frac_sch_type = 'Schedule:Year'
elsif max_oa_frac_sch.to_ScheduleConstant.is_initialized
max_oa_frac_sch = max_oa_frac_sch.to_ScheduleConstant.get
max_oa_frac_sch_type = 'Schedule:Constant'
elsif max_oa_frac_sch.to_ScheduleCompact.is_initialized
max_oa_frac_sch = max_oa_frac_sch.to_ScheduleCompact.get
max_oa_frac_sch_type = 'Schedule:Compact'
end
end

# Add EMS to "cap" the OA calculated by the
# Controller:MechanicalVentilation object
# to the design v_ot using the maximum OA
# fraction schedule

# Add EMS sensors
# OA mass flow calculated by the Controller:MechanicalVentilation
air_loop_hvac_name_ems = "EMS_#{air_loop_hvac.name.to_s.gsub(' ', '_')}"
oa_vrp_mass_flow = OpenStudio::Model::EnergyManagementSystemSensor.new(air_loop_hvac.model, 'Air System Outdoor Air Mechanical Ventilation Requested Mass Flow Rate')
oa_vrp_mass_flow.setKeyName(air_loop_hvac.name.to_s)
oa_vrp_mass_flow.setName("#{air_loop_hvac_name_ems}_OA_VRP")
# Actual sensed OA mass flow
oa_mass_flow = OpenStudio::Model::EnergyManagementSystemSensor.new(air_loop_hvac.model, 'Air System Outdoor Air Mass Flow Rate')
oa_mass_flow.setKeyName(air_loop_hvac.name.to_s)
oa_mass_flow.setName("#{air_loop_hvac_name_ems}_OA")
# Actual sensed volumetric OA flow
oa_vol_flow = OpenStudio::Model::EnergyManagementSystemSensor.new(air_loop_hvac.model, 'System Node Standard Density Volume Flow Rate')
oa_vol_flow.setKeyName("#{air_loop_hvac.name} Mixed Air Node")
oa_vol_flow.setName("#{air_loop_hvac_name_ems}_SUPPLY_FLOW")

# Add EMS actuator
max_oa_fraction = OpenStudio::Model::EnergyManagementSystemActuator.new(max_oa_frac_sch, max_oa_frac_sch_type, 'Schedule Value')
max_oa_fraction.setName("#{air_loop_hvac_name_ems}_MAX_OA_FRAC")

# Add EMS program
max_oa_ems_prog = OpenStudio::Model::EnergyManagementSystemProgram.new(air_loop_hvac.model)
max_oa_ems_prog.setName("#{air_loop_hvac.name}_MAX_OA_FRAC")
max_oa_ems_prog_body = <<-EMS
IF #{air_loop_hvac_name_ems}_OA > #{air_loop_hvac_name_ems}_OA_VRP,
SET #{air_loop_hvac_name_ems}_MAX_OA_FRAC = NULL,
ELSE,
IF #{air_loop_hvac_name_ems}_SUPPLY_FLOW > 0,
SET #{air_loop_hvac_name_ems}_MAX_OA_FRAC = #{v_ot} / #{air_loop_hvac_name_ems}_SUPPLY_FLOW,
ELSE,
SET #{air_loop_hvac_name_ems}_MAX_OA_FRAC = NULL,
ENDIF,
ENDIF
EMS
max_oa_ems_prog.setBody(max_oa_ems_prog_body)

max_oa_ems_prog_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(air_loop_hvac.model)
max_oa_ems_prog_manager.setName("SET_#{air_loop_hvac.name.to_s.gsub(' ', '_')}_MAX_OA_FRAC")
max_oa_ems_prog_manager.setCallingPoint('InsideHVACSystemIterationLoop')
max_oa_ems_prog_manager.addProgram(max_oa_ems_prog)

# Hard-size the sizing:system
# object with the calculated min OA flow rate
sizing_system = air_loop_hvac.sizingSystem
sizing_system.setDesignOutdoorAirFlowRate(v_ot)
sizing_system.setSystemOutdoorAirMethod('ZoneSum')

return true
end
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

New method that sets the MDP based on v_oz and v_ot based on a simplified e_v calculation.

# @todo, update this section when OS allows to adjust minimum zone ventilation efficiency
# In EnergyPlus this is done through the DesignSpecification:ZoneAirDistribution object
# which is then assigned to a Sizing:Zone object
sizing_zone.setDesignMinimumZoneVentilationEfficiency(0.6)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sets the minimum e_vz which wasn't possible prior to OS 3.0.

@lymereJ lymereJ requested a review from mdahlhausen September 7, 2021 20:14
Copy link
Collaborator

@mdahlhausen mdahlhausen left a comment

Choose a reason for hiding this comment

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

  • Add log/warning message for method that isn't supported for OS versions < 3.0 (add version check in code).
  • check alignment between system outdoor air method in sizing system and controller mechanical ventilation

@lymereJ
Copy link
Collaborator Author

lymereJ commented Sep 14, 2021

  • Add log/warning message for method that isn't supported for OS versions < 3.0 (add version check in code).
  • check alignment between system outdoor air method in sizing system and controller mechanical ventilation

I added a warning for the unsupported method.

As I expected, the fact that the controller mechanical ventilation is created by default and cannot be unassigned from the controller outdoor air (unless I'm mistaken) can potentially be an issue because if the OA flow rate specified at the sizing system level is lower than what is recalculated by the controller mechanical ventilation using the "zone sum" approach, the later is used during the simulation. Since this is can be an issue now, and will be if this PR is merged, I would be inclined to merge it as is, file an issue on the OpenStudio Github page, and reference this PR. What do you think?

@lymereJ lymereJ requested a review from mdahlhausen September 14, 2021 18:27
@lymereJ lymereJ merged commit c604a61 into 901_2016_2019 Sep 14, 2021
@mdahlhausen mdahlhausen deleted the 901_2019_add_cm_co_au_vav_vent branch April 15, 2022 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
90.1-2016/9 Flag PR targeting code changes related to the 90.1-2016/9 update
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants