ERV unit supply mass flow rate greater than Supply FanOnOff mass flow rate
Hello,
I used Energy Management System to control supply and exhaust FanOnOff (which is used in an ERV unit) air mass flow rate using actuator "Fan" with control type "Fan Air Mass Flow Rate". The EMS worked well but the supply and exhaust flow rate of ERV (Energy Recovery Ventilator) unit were not modified with the values of supply and exhaust FanOnOff air mass flow rate. Therefore, I received a value of zone mechanical ventilation mass flow rate which is different than the FanOnOff mass flow rate but is the same as ERV supply and exhaust flow rate predefined at the beginning of the simulation.
Does anybody have an idea for this? Did I make some mistakes here?
Thank you very much
Please find below my EMS snippet:
def arguments(model)
args = OpenStudio::Measure::OSArgumentVector.new
occupation_erv_fan_position = OpenStudio::Measure::OSArgument.makeDoubleArgument('occupation_erv_fan_position', true)
occupation_erv_fan_position.setDisplayName('Position of fan mass flow rate control during occupation period')
occupation_erv_fan_position.setDefaultValue(2)
args << occupation_erv_fan_position
absent_erv_fan_position = OpenStudio::Measure::OSArgument.makeDoubleArgument('absent_erv_fan_position', true)
absent_erv_fan_position.setDisplayName('Position of fan mass flow rate control during absent period')
absent_erv_fan_position.setDefaultValue(1)
args << absent_erv_fan_position
night_erv_fan_position = OpenStudio::Measure::OSArgument.makeDoubleArgument('night_erv_fan_position', true)
night_erv_fan_position.setDisplayName('Position of fan mass flow rate control during night time')
night_erv_fan_position.setDefaultValue(1)
args << night_erv_fan_position
return args
end
def run(model, runner, user_arguments)
super(model, runner, user_arguments)
# use the built-in error checking
if !runner.validateUserArguments(arguments(model), user_arguments)
return false
end
# assign the user inputs to variables
occupation_erv_fan_position = runner.getDoubleArgumentValue('occupation_erv_fan_position', user_arguments).to_f
absent_erv_fan_position = runner.getDoubleArgumentValue('absent_erv_fan_position', user_arguments).to_f
night_erv_fan_position = runner.getDoubleArgumentValue('night_erv_fan_position', user_arguments).to_f
# get thermal zones
thermal_zones = model.getThermalZones
thermal_zones.each do |thermal_zone|
zone_eqpt = thermal_zone.equipment # vector
zone_eqpt.each do |eqpt| # for each equipment
# Zone HVAC Energy Recovery Ventilator
if eqpt.to_ZoneHVACEnergyRecoveryVentilator.is_initialized
# get Energy Recovery Ventilator Unit
erv_unit = eqpt.to_ZoneHVACEnergyRecoveryVentilator.get
erv_supply_mass_flow_rate = TPEEHVACHelper.erv_supply_flow_rate(thermal_zone).to_f*1.204 # supply air flow rate is in m3/s and assuming that air density is of 1.204 kg/m3
erv_exhaust_mass_flow_rate = TPEEHVACHelper.erv_supply_flow_rate(thermal_zone).to_f*1.204 # supply air flow rate is in m3/s and assuming that air density is of 1.204 kg/m3
erv_supplyAirFan = erv_unit.supplyAirFan.to_FanOnOff.get
erv_exhaustAirFan = erv_unit.exhaustAirFan.to_FanOnOff.get
# Create EMS Actuator Objects
erv_supplyAirFan_ems_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(erv_supplyAirFan,"Fan","Fan Air Mass Flow Rate")
erv_supplyAirFan_ems_actuator.setName("erv_supplyAirFan_ems_actuator_#{thermal_zone.name.to_s}")
runner.registerInfo("EMS Actuator object named '#{erv_supplyAirFan_ems_actuator.name.to_s}' representing the mass flow rate of erv supply air fan named #{erv_supplyAirFan.name.to_s} added to the model.")
erv_exhaustAirFan_ems_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(erv_exhaustAirFan,"Fan","Fan Air Mass Flow Rate")
erv_exhaustAirFan_ems_actuator.setName("erv_exhaustAirFan_ems_actuator_#{thermal_zone.name.to_s}")
runner.registerInfo("EMS Actuator object named '#{erv_exhaustAirFan_ems_actuator.name.to_s}' representing the mass flow rate of erv supply air fan named #{erv_exhaustAirFan.name.to_s} added to the model.")
# Create new EnergyManagementSystem:Program object
erv_fan_mass_flow_rate_ems_prg = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
erv_fan_mass_flow_rate_ems_prg.setName("erv_fan_mass_flow_rate_ems_prg_#{thermal_zone.name.to_s}")
erv_fan_mass_flow_rate_ems_prg.addLine("IF ((Hour >= 0) && (Hour <= 6)) || (Hour >= 22)") # night time
erv_fan_mass_flow_rate_ems_prg.addLine("SET #{erv_supplyAirFan_ems_actuator.name} = #{erv_supply_mass_flow_rate}*#{night_erv_fan_position}/3.0")
erv_fan_mass_flow_rate_ems_prg.addLine("SET #{erv_exhaustAirFan_ems_actuator.name} = #{erv_exhaust_mass_flow_rate}*#{night_erv_fan_position}/3.0")
#erv_fan_mass_flow_rate_ems_prg.addLine("SET #{erv_flow_cst_sch_ems_actuator.name} = #{erv_exhaust_mass_flow_rate}*#{night_erv_fan_position}/3.0")
erv_fan_mass_flow_rate_ems_prg.addLine("ELSEIF (Hour >= 8) && (Hour <= 16)") # absent period
erv_fan_mass_flow_rate_ems_prg.addLine("SET #{erv_supplyAirFan_ems_actuator.name} = #{erv_supply_mass_flow_rate}*#{absent_erv_fan_position}/3.0")
erv_fan_mass_flow_rate_ems_prg.addLine("SET #{erv_exhaustAirFan_ems_actuator.name} = #{erv_exhaust_mass_flow_rate}*#{absent_erv_fan_position}/3.0")
#erv_fan_mass_flow_rate_ems_prg.addLine("SET #{erv_flow_cst_sch_ems_actuator.name} = #{erv_exhaust_mass_flow_rate}*#{absent_erv_fan_position}/3.0")
erv_fan_mass_flow_rate_ems_prg.addLine("ELSE") # occupation period
erv_fan_mass_flow_rate_ems_prg.addLine("SET #{erv_supplyAirFan_ems_actuator.name} = #{erv_supply_mass_flow_rate}*#{occupation_erv_fan_position}/3.0")
erv_fan_mass_flow_rate_ems_prg.addLine("SET #{erv_exhaustAirFan_ems_actuator.name} = #{erv_exhaust_mass_flow_rate}*#{occupation_erv_fan_position}/3.0")
#erv_fan_mass_flow_rate_ems_prg.addLine("SET #{erv_flow_cst_sch_ems_actuator.name} = #{erv_exhaust_mass_flow_rate}*#{occupation_erv_fan_position}/3.0")
erv_fan_mass_flow_rate_ems_prg.addLine("ENDIF")
# create new EnergyManagementSystem:ProgramCallingManager object
ems_prgm_calling_mngr = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
ems_prgm_calling_mngr.setName("erv_fan_mass_flow_rate_ems_call_#{thermal_zone.name.to_s}")
ems_prgm_calling_mngr.setCallingPoint("BeginTimestepBeforePredictor")
ems_prgm_calling_mngr.addProgram(erv_fan_mass_flow_rate_ems_prg)
runner.registerInfo("EMS Program Calling Manager object named '#{ems_prgm_calling_mngr.name}' added to call #{erv_fan_mass_flow_rate_ems_prg.name} EMS programs.")
end
end
end
return true
end
And below is the difference between mechanical zone ventilation mass flow rate and controlled fan onoff mass flow rate of ERV unit:
Long