Multizone VAV air handling unit controller. Block that is applied for multizone VAV AHU control. It outputs the supply fan status
and the operation speed, outdoor and return air damper position, supply air
temperature setpoint and the valve position of the cooling and heating coils.
It is implemented according to the Section 5.16 of ASHRAE Guideline 36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV;
block Controller "Multizone VAV air handling unit controller"

  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.EnergyStandard eneStd
    "Energy standard, ASHRAE 90.1 or Title 24";
  parameter Types.VentilationStandard venStd
    "Ventilation standard, ASHRAE 62.1 or Title 24";
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.ASHRAEClimateZone ashCliZon=Buildings.Controls.OBC.ASHRAE.G36.Types.ASHRAEClimateZone.Not_Specified
    "ASHRAE climate zone"
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.Title24ClimateZone tit24CliZon=Buildings.Controls.OBC.ASHRAE.G36.Types.Title24ClimateZone.Not_Specified
    "California Title 24 climate zone"
  parameter Boolean have_frePro=true
    "True: enable freeze protection"
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.FreezeStat freSta=Buildings.Controls.OBC.ASHRAE.G36.Types.FreezeStat.Hardwired_to_equipment
    "Type of freeze stat"
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection minOADes=Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
    "Type of outdoor air section"
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl buiPreCon=
      Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefFan
    "Type of building pressure control system"
  parameter Boolean have_ahuRelFan=true
    "True: relief fan is part of AHU; False: the relief fans group that may associate multiple AHUs"
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer ecoHigLimCon=Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.
      FixedDryBulb
    "Economizer high limit control device"
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil cooCoi=Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.WaterBased
    "Cooling coil type"
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil heaCoi=Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.WaterBased
    "Heating coil type"

  parameter Boolean have_perZonRehBox=false
    "Check if there is any VAV-reheat boxes on perimeter zones"

  parameter Real VUncDesOutAir_flow(unit="m3/s")=0
    "Uncorrected design outdoor airflow rate, including diversity where applicable. It can be determined using the 62MZCalc spreadsheet from ASHRAE 62.1 User's Manual"
  parameter Real VDesTotOutAir_flow(unit="m3/s")=0
    "Design total outdoor airflow rate. It can be determined using the 62MZCalc spreadsheet from ASHRAE 62.1 User's Manual"
  parameter Real VAbsOutAir_flow(unit="m3/s")=0
    "Design outdoor airflow rate when all zones with CO2 sensors or occupancy sensors are unpopulated. Needed when complying with Title 24 requirements"
  parameter Real VDesOutAir_flow(unit="m3/s")=0
    "Design minimum outdoor airflow rate with the areas served by the system are occupied at their design population, including diversity where applicable. Needed when complying with Title 24 requirements"
  // ----------- parameters for fan speed control  -----------
  parameter Real pIniSet(
    unit="Pa",
    displayUnit="Pa")=120
    "Initial pressure setpoint for fan speed control"
  parameter Real pMinSet(
    unit="Pa",
    displayUnit="Pa")=25
    "Minimum pressure setpoint for fan speed control"
  parameter Real pMaxSet(
    unit="Pa",
    displayUnit="Pa")=1000
    "Duct design maximum static pressure. It is the Max_DSP shown in Section 3.2.1.1 of Guideline 36"
  parameter Real pDelTim(unit="s")=600
    "Delay time after which trim and respond is activated"
  parameter Real pSamplePeriod(unit="s")=120
    "Sample period"
  parameter Integer pNumIgnReq=2
    "Number of ignored requests"
  parameter Real pTriAmo(
    unit="Pa",
    displayUnit="Pa")=-12.0
    "Trim amount"
  parameter Real pResAmo(
    unit="Pa",
    displayUnit="Pa")=15
    "Respond amount (must be opposite in to trim amount)"
  parameter Real pMaxRes(
    unit="Pa",
    displayUnit="Pa")=32
    "Maximum response per time interval (same sign as respond amount)"
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController fanSpeCon=Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Supply fan speed PID controller"
  parameter Real kFanSpe(unit="1")=0.1
    "Gain of supply fan speed PID controller"
  parameter Real TiFanSpe(unit="s")=60
    "Time constant of integrator block for supply fan speed PID controller"
  parameter Real TdFanSpe(unit="s")=0.1
    "Time constant of derivative block for supply fan speed PID controller"
  final parameter Real supFanSpe_max=1
    "Maximum allowed supply fan speed"
  parameter Real supFanSpe_min=0.1
    "Lowest allowed supply fan speed if fan is on"
  parameter Real iniFanSpe(unit="1")=supFanSpe_min
    "Initial speed when fan is enabled. It has to be greater than the lowest allowed speed"

  // ----------- parameters for supply air temperature control  -----------
  parameter Real TSupCoo_min(
    unit="K",
    displayUnit="degC")=285.15
    "Lowest cooling supply air temperature setpoint when the outdoor air temperature is at the higher value of the reset range and above"
  parameter Real TSupCoo_max(
    unit="K",
    displayUnit="degC")=291.15
    "Highest cooling supply air temperature setpoint. It is typically 18 degC (65 degF)
    in mild and dry climates, 16 degC (60 degF) or lower in humid climates"
  parameter Real TOut_min(
    unit="K",
    displayUnit="degC")=289.15
    "Lower value of the outdoor air temperature reset range. Typically value is 16 degC (60 degF)"
  parameter Real TOut_max(
    unit="K",
    displayUnit="degC")=294.15
    "Higher value of the outdoor air temperature reset range. Typically value is 21 degC (70 degF)"
  parameter Real TSupWarUpSetBac(
    unit="K",
    displayUnit="degC")=308.15
    "Supply temperature in warm up and set back mode"
  parameter Real delTimSupTem(unit="s")=600
    "Delay timer"
  parameter Real samPerSupTem(unit="s")=120
    "Sample period of component"
  parameter Integer ignReqSupTem=2
    "Number of ignorable requests for TrimResponse logic"
  parameter Real triAmoSupTem(
    unit="K",
    displayUnit="K")=0.1
    "Trim amount"
  parameter Real resAmoSupTem(
    unit="K",
    displayUnit="K")=-0.2
    "Response amount"
  parameter Real maxResSupTem(
    unit="K",
    displayUnit="K")=-0.6
    "Maximum response per time interval"

  // ----------- parameters for heating and cooling coil control  -----------
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController valCon=Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller for coil valves control"
  parameter Real kVal(unit="1")=0.05
    "Gain of controller for valve control"
  parameter Real TiVal(unit="s")=600
    "Time constant of integrator block for valve control"
  parameter Real TdVal(unit="s")=0.1
    "Time constant of derivative block for valve control"
  parameter Real uHeaCoi_max=-0.25
    "Upper limit of controller signal when heating coil is off. Require -1 < uHea_max < uCoo_min < 1."
  parameter Real uCooCoi_min=0.25
    "Lower limit of controller signal when cooling coil is off. Require -1 < uHea_max < uCoo_min < 1."

  // ----------- parameters for economizer control  -----------
  // Limits
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController minOAConTyp=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of minimum outdoor air controller"
  parameter Real kMinOA(unit="1")=0.03
    "Gain of controller"
  parameter Real TiMinOA(unit="s")=120
    "Time constant of integrator block"
  parameter Real TdMinOA(unit="s")=0.1
    "Time constant of derivative block"
  parameter Boolean have_CO2Sen=false
    "True: some zones have CO2 sensor"
  parameter Real dpAbsMinOutDam=5
    "Absolute minimum pressure difference across the minimum outdoor air damper. It provides the absolute minimum outdoor airflow"
  parameter Real dpDesMinOutDam(unit="Pa")=20
    "Design minimum pressure difference across the minimum outdoor air damper. It provides the design minimum outdoor airflow"
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController dpConTyp=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of differential pressure setpoint controller"
  parameter Real kDp(unit="1")=1
    "Gain of controller"
  parameter Real TiDp(unit="s")=0.5
    "Time constant of integrator block"
  parameter Real TdDp(unit="s")=0.1
    "Time constant of derivative block"
  parameter Real uRetDam_min(unit="1")=0.5
    "Loop signal value to start decreasing the maximum return air damper position"
  // Enable
  parameter Real delTOutHis(
    unit="K",
    displayUnit="K")=1
    "Delta between the temperature hysteresis high and low limit"
  parameter Real delEntHis(unit="J/kg")=1000
    "Delta between the enthalpy hysteresis high and low limits"
  parameter Real retDamFulOpeTim(unit="s")=180
    "Time period to keep return air damper fully open before releasing it for minimum outdoor airflow control
    at disable to avoid pressure fluctuations"
  parameter Real disDel(unit="s")=15
    "Short time delay before closing the outdoor air damper at disable to avoid pressure fluctuations"
  // Commissioning
  parameter Real retDamPhy_max(unit="1")=1.0
    "Physically fixed maximum position of the return air damper"
  parameter Real retDamPhy_min(unit="1")=0.0
    "Physically fixed minimum position of the return air damper"
  parameter Real outDamPhy_max(unit="1")=1.0
    "Physically fixed maximum position of the outdoor air damper"
  parameter Real outDamPhy_min(unit="1")=0.0
    "Physically fixed minimum position of the outdoor air damper"
  parameter Real minOutDamPhy_max(unit="1")=1.0
    "Physically fixed maximum position of the minimum outdoor air damper"
  parameter Real minOutDamPhy_min(unit="1")=0.0
    "Physically fixed minimum position of the minimum outdoor air damper"
  parameter Real uHeaMax(unit="1")=-0.25
    "Lower limit of controller input when outdoor damper opens (see diagram)"
  parameter Real uCooMin(unit="1")=+0.25
    "Upper limit of controller input when return damper is closed (see diagram)"

  // ----------- parameters for freeze protection -----------
  parameter Integer minHotWatReq=2
    "Minimum heating hot-water plant request to active the heating plant"
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController freProHeaCoiCon=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Freeze protection heating coil controller"
  parameter Real kFrePro(unit="1")=0.05
    "Gain of coil controller"
  parameter Real TiFrePro(unit="s")=120
    "Time constant of integrator block"
  parameter Real TdFrePro(unit="s")=0.1
    "Time constant of derivative block"
  parameter Real yMaxFrePro=1
    "Upper limit of output"
  parameter Real yMinFrePro=0
    "Lower limit of output"

  // ----------- Building pressure control parameters -----------
  parameter Real dpBuiSet(
    unit="Pa",
    displayUnit="Pa")=12
    "Building static pressure difference relative to ambient (positive to pressurize the building)"
  parameter Real kRelDam(unit="1")=0.5
    "Gain, applied to building pressure control error normalized with dpBuiSet"
//   parameter Real kRelFan(unit="1")=1
//     "Gain, normalized using dpBuiSet"
//
//   parameter Real minSpeRelFan(unit="1")=0.1
//     "Minimum relief fan speed"
//
  parameter Real difFloSet(unit="m3/s")=0.1
    "Airflow differential between supply air and return air fans required to maintain building pressure at desired pressure"
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController retFanCon=Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller for return fan"
  parameter Real kRetFan(unit="1")=1
    "Gain, normalized using dpBuiSet"
  parameter Real TiRetFan(unit="s")=0.5
    "Time constant of integrator block"
  parameter Real TdRetFan(unit="s")=0.1
    "Time constant of derivative block"
  final parameter Real retFanSpe_max=1
    "Maximum return fan speed"
  parameter Real retFanSpe_min=0.1
    "Minimum return fan speed"

  parameter Real p_rel_RetFan_min(
    unit="Pa",
    displayUnit="Pa")=2.4
    "Minimum return fan discharge static pressure difference setpoint"
  parameter Real p_rel_RetFan_max(
    unit="Pa",
    displayUnit="Pa")=40
    "Maximum return fan discharge static pressure difference setpoint"
  parameter Real relFanSpe_min(
    final min=0,
    final max=1)= 0.1
    "Relief fan minimum speed"
  parameter Real kRelFan(unit="1")=1
    "Gain of relief fan controller, normalized using dpBuiSet"

  // ----------- Advanced parameters -----------
  parameter Real Thys=0.25 "Hysteresis for checking temperature difference"
  parameter Real posHys=0.01
    "Hysteresis for checking valve position difference"
  parameter Real hys = 0.005
    "Hysteresis for checking the relief fan controller output value"

  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uAhuOpeMod
    "Operation mode for AHU operation"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uZonPreResReq
    "Zone static pressure reset requests"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpDuc(
    final unit="Pa",
    displayUnit="Pa",
    final quantity="PressureDifference") "Measured duct static pressure"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "Outdoor air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uZonTemResReq
    "Zone cooling supply air temperature reset request"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SupFan
    "Supply fan status"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TAirSup(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "Measured supply air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VSumAdjPopBreZon_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1
    "Sum of the adjusted population component breathing zone flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VSumAdjAreBreZon_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1
    "Sum of the adjusted area component breathing zone flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VSumZonPri_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1
    "Sum of the zone primary airflow rates for all zones in all zone groups that are in occupied mode"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uOutAirFra_max(
    final min=0,
    final unit="1")
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1
    "Maximum zone outdoor air fraction, equals to the maximum of primary outdoor air fraction of all zones"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VSumZonAbsMin_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Sum of the zone absolute minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VSumZonDesMin_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Sum of the zone design minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VAirOut_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    if (minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
     or minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.SingleDamper)
    "Measured outdoor air volumetric flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uCO2Loo_max(
    final unit="1")
    if (have_CO2Sen and venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24)
    "Maximum zone CO2 control loop output"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpMinOutDam(
    final unit="Pa",
    displayUnit="Pa",
    final quantity="PressureDifference")
    if minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure
    "Measured pressure difference across the minimum outdoor air damper"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TAirRet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature") if (ecoHigLimCon == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.DifferentialDryBulb
     or ecoHigLimCon == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.FixedDryBulbWithDifferentialDryBulb)
    "Used only for fixed plus differential dry bulb temperature high limit cutoff"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput hAirOut(
    final unit="J/kg",
    final quantity="SpecificEnergy")
    if (ecoHigLimCon == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.DifferentialEnthalpyWithFixedDryBulb
     or ecoHigLimCon == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.FixedEnthalpyWithFixedDryBulb)
    "Outdoor air enthalpy"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput hAirRet(
    final unit="J/kg",
    final quantity="SpecificEnergy")
    if (eneStd == Buildings.Controls.OBC.ASHRAE.G36.Types.EnergyStandard.ASHRAE90_1
     and ecoHigLimCon == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.DifferentialEnthalpyWithFixedDryBulb)
    "OA enthalpy high limit cutoff. For differential enthalpy use return air enthalpy measurement"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1FreSta
    if freSta == Buildings.Controls.OBC.ASHRAE.G36.Types.FreezeStat.Hardwired_to_BAS and
    have_frePro
    "Freeze protection stat signal. The stat is normally close (the input is normally true), when enabling freeze protection, the input becomes false"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SofSwiRes if (freSta ==
    Buildings.Controls.OBC.ASHRAE.G36.Types.FreezeStat.No_freeze_stat or freSta ==
    Buildings.Controls.OBC.ASHRAE.G36.Types.FreezeStat.Hardwired_to_equipment)
     and have_frePro
    "Freeze protection reset signal from software switch"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1RelFan if buiPreCon ==
    Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefFan and not
    have_ahuRelFan          "Relief fan status"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TAirMix(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    if heaCoi==Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.WaterBased
       or heaCoi==Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.Electric
    "Measured mixed air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpBui(
    final unit="Pa",
    displayUnit="Pa",
    final quantity="PressureDifference")
    if (buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefDamper
     or buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefFan
     or buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanDp)
    "Measured building static pressure difference, relative to ambient (positive if pressurized)"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VAirSup_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    if buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanMeasuredAir
    "Measured AHU supply airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VAirRet_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    if buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanMeasuredAir
    "Measured AHU return airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TAirSupSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "AHU supply air temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VEffAirOut_flow_min(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1
    "Effective minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMinOutDam(
    final min=0,
    final max=1,
    final unit="1")
    if minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
    "Minimum outdoor air damper commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1MinOutDam
    if minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure
    "Minimum outdoor air damper command on"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDam(
    final min=0,
    final max=1,
    final unit="1")
    "Return air damper commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRelDam(
    final min=0,
    final max=1,
    final unit="1")
    if buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefDamper
       or buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanMeasuredAir
       or buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanDp
    "Relief air damper commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOutDam(
    final min=0,
    final max=1,
    final unit="1") "Economizer outdoor air damper commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1EneCHWPum
 if have_frePro
    "Commanded on to energize chilled water pump"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1SupFan
    "Supply fan command on"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySupFan(
    final min=0,
    final max=1,
    final unit="1") "Air handler supply fan commanded speed"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1RetFan if (buiPreCon ==
    Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanMeasuredAir
     or buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanDp)
    "Return fan commanded on"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetFan(
    final min=0,
    final max=1,
    final unit="1")
    if (buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanMeasuredAir
        or buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanDp)
    "Return fan commanded speed"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1RelFan if buiPreCon ==
    Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefFan
    "Relief fan commanded on"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRelFan(
    final min=0,
    final max=1,
    final unit="1")
    if buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefFan
    "Relief fan commanded speed"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1RelDam if buiPreCon ==
    Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefFan
    "True: 2-position relief damper is commanded open"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yCooCoi(
    final min=0,
    final max=1,
    final unit="1") if (cooCoi == Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.WaterBased
     or cooCoi == Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.DXCoil)
                    "Cooling coil valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHeaCoi(
    final min=0,
    final max=1,
    final unit="1")
    if heaCoi==Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.WaterBased
    or heaCoi==Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.Electric
    "Heating coil valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yAla if have_frePro
    "Alarm level"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yDpBui(
    final unit="Pa",
    displayUnit="Pa",
    final quantity="PressureDifference")
    if (buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefFan
        and have_ahuRelFan) or buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanDp
    "Building static pressure difference, relative to ambient (positive if pressurized)"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dpDisSet(
    final unit="Pa",
    displayUnit="Pa",
    final quantity="PressureDifference")
    if buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanDp
    "Return fan discharge static pressure setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yChiWatResReq
    if cooCoi == Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.WaterBased
    "Chilled water reset request"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yChiPlaReq
    if cooCoi == Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.WaterBased
    "Chiller plant request"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yHotWatResReq
    if heaCoi==Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.WaterBased
    "Hot water reset request"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput yHotWatPlaReq
    if heaCoi==Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.WaterBased
    "Hot water plant request"

  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold freProMod
    if heaCoi==Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.WaterBased
    "Check if it is in freeze protection mode"
  Buildings.Controls.OBC.CDL.Integers.Switch intSwi
    if heaCoi==Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.WaterBased
    "Hot water plant request"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.FreezeProtection frePro(
    final have_frePro=have_frePro,
    final buiPreCon=buiPreCon,
    final minOADes=minOADes,
    final freSta=freSta,
    final heaCoi=heaCoi,
    final cooCoi=cooCoi,
    final minHotWatReq=minHotWatReq,
    final heaCoiCon=freProHeaCoiCon,
    final k=kFrePro,
    final Ti=TiFrePro,
    final Td=TdFrePro,
    final yMax=yMaxFrePro,
    final yMin=yMinFrePro,
    final Thys=Thys) "Freeze protection"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.PlantRequests plaReq(
    final heaCoi=heaCoi,
    final cooCoi=cooCoi,
    final Thys=Thys,
    final posHys=posHys) "Plant requests"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Controller ecoCon(
    final minOADes=minOADes,
    final buiPreCon=buiPreCon,
    final eneStd=eneStd,
    final ecoHigLimCon=ecoHigLimCon,
    final ashCliZon=ashCliZon,
    final tit24CliZon=tit24CliZon,
    final minSpe=supFanSpe_min,
    final minOAConTyp=minOAConTyp,
    final kMinOA=kMinOA,
    final TiMinOA=TiMinOA,
    final TdMinOA=TdMinOA,
    final venStd=venStd,
    final dpDesMinOutDam=dpDesMinOutDam,
    final dpConTyp=dpConTyp,
    final kDp=kDp,
    final TiDp=TiDp,
    final TdDp=TdDp,
    final uRetDam_min=uRetDam_min,
    final retDamPhy_max=retDamPhy_max,
    final retDamPhy_min=retDamPhy_min,
    final outDamPhy_max=outDamPhy_max,
    final outDamPhy_min=outDamPhy_min,
    final minOutDamPhy_max=minOutDamPhy_max,
    final minOutDamPhy_min=minOutDamPhy_min,
    final delTOutHis=delTOutHis,
    final delEntHis=delEntHis,
    final retDamFulOpeTim=retDamFulOpeTim,
    final disDel=disDel,
    final uHeaMax=uHeaMax,
    final uCooMin=uCooMin,
    final uOutDamMax=(uHeaMax + uCooMin)/2,
    final uRetDamMin=(uHeaMax + uCooMin)/2,
    final have_CO2Sen=have_CO2Sen,
    final dpAbsMinOutDam=dpAbsMinOutDam) "Economizer controller"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.SupplyFan conSupFan(
    final have_perZonRehBox=have_perZonRehBox,
    final iniSet=pIniSet,
    final minSet=pMinSet,
    final maxSet=pMaxSet,
    final delTim=pDelTim,
    final samplePeriod=pSamplePeriod,
    final numIgnReq=pNumIgnReq,
    final triAmo=pTriAmo,
    final resAmo=pResAmo,
    final maxRes=pMaxRes,
    final controllerType=fanSpeCon,
    final k=kFanSpe,
    final Ti=TiFanSpe,
    final Td=TdFanSpe,
    final maxSpe=supFanSpe_max,
    final minSpe=supFanSpe_min,
    final iniSpe=iniFanSpe)     "Supply fan speed setpoint"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.SupplySignals supSig(
    final have_heaCoi=heaCoi==Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.WaterBased or heaCoi==Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.Electric,
    final have_cooCoi=cooCoi == Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.WaterBased
         or cooCoi == Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.DXCoil,
    final controllerType=valCon,
    final kTSup=kVal,
    final TiTSup=TiVal,
    final TdTSup=TdVal,
    final uHea_max=uHeaCoi_max,
    final uCoo_min=uCooCoi_min) "Heating and cooling valve position"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.SupplyTemperature conTSupSet(
    final TSupCoo_min=TSupCoo_min,
    final TSupCoo_max=TSupCoo_max,
    final TOut_min=TOut_min,
    final TOut_max=TOut_max,
    final TSupWarUpSetBac=TSupWarUpSetBac,
    final delTim=delTimSupTem,
    final samplePeriod=samPerSupTem,
    final numIgnReq=ignReqSupTem,
    final triAmo=triAmoSupTem,
    final resAmo=resAmoSupTem,
    final maxRes=maxResSupTem) "Supply temperature setpoint"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.ASHRAE62_1.AHU ashOutAirSet(
    final minOADes=minOADes,
    final VUncDesOutAir_flow=VUncDesOutAir_flow,
    final VDesTotOutAir_flow=VDesTotOutAir_flow)
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1
    "Minimum outdoor airflow setpoint, when complying with ASHRAE 62.1 requirements"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefDamper relDam(
    final dpBuiSet=dpBuiSet,
    final k=kRelDam) if buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefDamper
    "Relief damper control for AHUs using actuated dampers without fan"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReturnFanDirectPressure retFanDpCon(
    final dpBuiSet=dpBuiSet,
    final p_rel_RetFan_min=p_rel_RetFan_min,
    final p_rel_RetFan_max=p_rel_RetFan_max,
    final disSpe_min=retFanSpe_min,
    final disSpe_max=retFanSpe_max,
    final conTyp=retFanCon,
    final k=kRetFan,
    final Ti=TiRetFan,
    final Td=TdRetFan) if buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanDp
    "Return fan control with direct building pressure control, using the minimum outdoor air damper"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReturnFanAirflowTracking retFanAirTra(
    final difFloSet=difFloSet,
    final conTyp=retFanCon,
    final k=kRetFan,
    final Ti=TiRetFan,
    final Td=TdRetFan,
    final maxSpe=retFanSpe_max,
    final minSpe=retFanSpe_min) if buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanMeasuredAir
    "Return fan control for AHUs using return fan with airflow tracking"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.Title24.AHU tit24OutAirSet(
    final minOADes=minOADes,
    final have_CO2Sen=have_CO2Sen,
    final VAbsOutAir_flow=VAbsOutAir_flow,
    final VDesOutAir_flow=VDesOutAir_flow)
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Minimum outdoor airflow setpoint, when complying with Title 24 requirements"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefFan relFanCon(
    final relFanSpe_min=relFanSpe_min,
    final dpBuiSet=dpBuiSet,
    final k=kRelFan,
    final hys=hys) if have_ahuRelFan and buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefFan
    "Control of relief fan when it is part of AHU"

equation
  connect(conSupFan.uZonPreResReq, uZonPreResReq)
  connect(dpDuc, conSupFan.dpDuc)
  connect(conTSupSet.TOut, TOut)
  connect(conTSupSet.uZonTemResReq, uZonTemResReq)
  connect(u1SupFan, conTSupSet.u1SupFan)
  connect(u1SupFan, supSig.u1SupFan)
  connect(conTSupSet.TAirSupSet, supSig.TAirSupSet)
  connect(supSig.TAirSup, TAirSup)
  connect(uOutAirFra_max, ashOutAirSet.uOutAirFra_max)
  connect(plaReq.yChiWatResReq, yChiWatResReq)
  connect(plaReq.yChiPlaReq, yChiPlaReq)
  connect(plaReq.yHotWatResReq, yHotWatResReq)
  connect(ashOutAirSet.effOutAir_normalized, ecoCon.VOutMinSet_flow_normalized)
  connect(ecoCon.dpMinOutDam, dpMinOutDam)
  connect(supSig.uTSup, ecoCon.uTSup)
  connect(TOut, ecoCon.TOut)
  connect(TAirRet, ecoCon.TAirRet)
  connect(ecoCon.hAirOut, hAirOut)
  connect(hAirRet, ecoCon.hAirRet)
  connect(u1SupFan, ecoCon.u1SupFan)
  connect(ecoCon.yOutDam_min, frePro.uOutDamPosMin)
  connect(TAirSup, frePro.TAirSup)
  connect(frePro.u1FreSta, u1FreSta)
  connect(frePro.u1SofSwiRes, u1SofSwiRes)
  connect(frePro.TAirMix, TAirMix)
  connect(ashOutAirSet.VEffAirOut_flow_min, VEffAirOut_flow_min)
  connect(ecoCon.yRelDam, yRelDam)
  connect(frePro.yFreProSta, ecoCon.uFreProSta)
  connect(ecoCon.yOutDam, frePro.uOutDam)
  connect(ecoCon.yRetDam, frePro.uRetDam)
  connect(supSig.yHeaCoi, frePro.uHeaCoi)
  connect(conSupFan.ySupFan, frePro.uSupFan)
  connect(supSig.yCooCoi, frePro.uCooCoi)
  connect(frePro.y1EneCHWPum, y1EneCHWPum)
  connect(frePro.yRetDam, yRetDam)
  connect(frePro.yOutDam, yOutDam)
  connect(ecoCon.yMinOutDam, frePro.uMinOutDam)
  connect(frePro.yMinOutDam, yMinOutDam)
  connect(frePro.ySupFan, ySupFan)
  connect(frePro.yRetFan, yRetFan)
  connect(frePro.yCooCoi, yCooCoi)
  connect(frePro.yHeaCoi, yHeaCoi)
  connect(intSwi.y, yHotWatPlaReq)
  connect(plaReq.yHotWatPlaReq, intSwi.u3)
  connect(freProMod.y, intSwi.u2)
  connect(frePro.yRelFan, yRelFan)
  connect(relDam.dpBui, dpBui)
  connect(relDam.yRelDam, yRelDam)
  connect(retFanAirTra.VAirSup_flow, VAirSup_flow)
  connect(retFanAirTra.VAirRet_flow, VAirRet_flow)
  connect(dpBui, retFanDpCon.dpBui)
  connect(retFanDpCon.yDpBui, yDpBui)
  connect(retFanDpCon.dpDisSet, dpDisSet)
  connect(u1SupFan, relDam.u1SupFan)
  connect(u1SupFan, retFanAirTra.u1SupFan)
  connect(u1SupFan, retFanDpCon.u1SupFan)
  connect(TAirSup, plaReq.TAirSup)
  connect(conTSupSet.TAirSupSet, plaReq.TAirSupSet)
  connect(frePro.yHotWatPlaReq, intSwi.u1)
  connect(retFanAirTra.yRetFan, frePro.uRetFan)
  connect(retFanDpCon.yRetFan, frePro.uRetFan)
  connect(frePro.yAla, yAla)
  connect(conTSupSet.TAirSupSet, TAirSupSet)
  connect(tit24OutAirSet.effAbsOutAir_normalized, ecoCon.effAbsOutAir_normalized)
  connect(tit24OutAirSet.effDesOutAir_normalized, ecoCon.effDesOutAir_normalized)
  connect(uCO2Loo_max, ecoCon.uCO2Loo_max)
  connect(uCO2Loo_max, tit24OutAirSet.uCO2Loo_max)
  connect(tit24OutAirSet.effOutAir_normalized, ecoCon.VOutMinSet_flow_normalized)
  connect(VAirOut_flow, tit24OutAirSet.VAirOut_flow)
  connect(VAirOut_flow, ashOutAirSet.VAirOut_flow)
  connect(ashOutAirSet.outAir_normalized, ecoCon.VOut_flow_normalized)
  connect(tit24OutAirSet.outAir_normalized, ecoCon.VOut_flow_normalized)
  connect(VSumZonDesMin_flow, tit24OutAirSet.VSumZonDesMin_flow)
  connect(VSumZonAbsMin_flow, tit24OutAirSet.VSumZonAbsMin_flow)
  connect(VSumZonPri_flow, ashOutAirSet.VSumZonPri_flow)
  connect(VSumAdjAreBreZon_flow, ashOutAirSet.VSumAdjAreBreZon_flow)
  connect(VSumAdjPopBreZon_flow, ashOutAirSet.VSumAdjPopBreZon_flow)
  connect(uAhuOpeMod, conSupFan.uOpeMod)
  connect(uAhuOpeMod, conTSupSet.uOpeMod)
  connect(uAhuOpeMod, ecoCon.uOpeMod)
  connect(ecoCon.y1MinOutDam, frePro.u1MinOutDam)
  connect(frePro.y1MinOutDam, y1MinOutDam)
  connect(retFanDpCon.yRelDam, yRelDam)
  connect(u1RelFan, frePro.u1RelFan)
  connect(retFanAirTra.y1RetFan, frePro.u1RetFan)
  connect(retFanDpCon.y1RetFan, frePro.u1RetFan)
  connect(frePro.y1RelFan, y1RelFan)
  connect(frePro.yFreProSta, freProMod.u)
  connect(conSupFan.y1SupFan, frePro.u1SupFan)
  connect(frePro.y1SupFan, y1SupFan)
  connect(frePro.y1RetFan, y1RetFan)
  connect(ecoCon.yEnaMinOut, retFanDpCon.u1MinOutAirDam)
  connect(dpBui, relFanCon.dpBui)
  connect(u1SupFan, relFanCon.u1SupFan)
  connect(relFanCon.yDpBui, yDpBui)
  connect(relFanCon.yRelFan, frePro.uRelFan)
  connect(relFanCon.y1RelFan, frePro.u1RelFan)
  connect(conSupFan.ySupFan, ecoCon.uSupFan)
  connect(frePro.yCooCoi, plaReq.uCooCoiSet)
  connect(frePro.yHeaCoi, plaReq.uHeaCoiSet)
  connect(frePro.y1RelDam, y1RelDam)
end Controller;


within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone;
package VAV "Sequences for multi zone VAV AHU control"
end VAV;


Multi zone VAV AHU economizer control sequence. Multi zone VAV AHU economizer control sequence that calculates
outdoor and return air damper positions based on ASHRAE
Guidline 36, May 2020, Sections: 5.16.2.3,5.16.4, 5.16.5, 5.16.6, 5.16.7.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers;
block Controller
  "Multi zone VAV AHU economizer control sequence"

  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection minOADes
    "Design of minimum outdoor air and economizer function";
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl buiPreCon
    "Type of building pressure control system";
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.EnergyStandard eneStd
    "Energy standard, ASHRAE 90.1 or Title 24";
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer ecoHigLimCon
    "Economizer high limit control device";
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.ASHRAEClimateZone ashCliZon=Buildings.Controls.OBC.ASHRAE.G36.Types.ASHRAEClimateZone.Not_Specified
    "ASHRAE climate zone"
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.Title24ClimateZone tit24CliZon=Buildings.Controls.OBC.ASHRAE.G36.Types.Title24ClimateZone.Not_Specified
    "California Title 24 climate zone"

  // Limits
  parameter Real minSpe(unit="1")=0.1
    "Minimum supply fan speed"
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController minOAConTyp=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of minimum outdoor air controller"
  parameter Real kMinOA(unit="1")=1
    "Gain of controller"
  parameter Real TiMinOA(unit="s")=0.5
    "Time constant of integrator block"
  parameter Real TdMinOA(unit="s")=0.1
    "Time constant of derivative block"
  parameter Types.VentilationStandard venStd=Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1
    "Ventilation standard, ASHRAE 62.1 or Title 24"
  parameter Boolean have_CO2Sen=false
    "True: some zones have CO2 sensor"
  parameter Real dpAbsMinOutDam=5
    "Absolute minimum pressure difference across the minimum outdoor air damper. It provides the absolute minimum outdoor airflow"
  parameter Real dpDesMinOutDam(unit="Pa")=20
    "Design minimum pressure difference across the minimum outdoor air damper. It provides the design minimum outdoor airflow"
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController dpConTyp=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PID
    "Type of differential pressure setpoint controller"
  parameter Real kDp(unit="1")=1
    "Gain of controller"
  parameter Real TiDp(unit="s")=0.5
    "Time constant of integrator block"
  parameter Real TdDp(unit="s")=0.1
    "Time constant of derivative block"
  parameter Real uRetDam_min(unit="1")=0.5
    "Loop signal value to start decreasing the maximum return air damper position"

  // Enable
  parameter Real delTOutHis(
    unit="K",
    displayUnit="K")=1
    "Delta between the temperature hysteresis high and low limit"
  parameter Real delEntHis(unit="J/kg")=1000
    "Delta between the enthalpy hysteresis high and low limits"
  parameter Real retDamFulOpeTim(unit="s")=180
    "Time period to keep RA damper fully open before releasing it for minimum outdoor airflow control at disable to avoid pressure fluctuations"
  parameter Real disDel(unit="s")=15
    "Short time delay before closing the OA damper at disable to avoid pressure fluctuations"

  // Commissioning
  parameter Real retDamPhy_max(unit="1")=1.0
    "Physically fixed maximum position of the return air damper"
  parameter Real retDamPhy_min(unit="1")=0.0
    "Physically fixed minimum position of the return air damper"
  parameter Real outDamPhy_max(unit="1")=1.0
    "Physically fixed maximum position of the outdoor air damper"
  parameter Real outDamPhy_min(unit="1")=0.0
    "Physically fixed minimum position of the outdoor air damper"
  parameter Real minOutDamPhy_max(unit="1")=1.0
    "Physically fixed maximum position of the minimum outdoor air damper"
  parameter Real minOutDamPhy_min(unit="1")=0.0
    "Physically fixed minimum position of the minimum outdoor air damper"
  parameter Real uHeaMax(unit="1")=-0.25
    "Lower limit of controller input when outdoor damper opens (see diagram)"
  parameter Real uCooMin(unit="1")=+0.25
    "Upper limit of controller input when return damper is closed (see diagram)"
  parameter Real uOutDamMax(unit="1")=(uHeaMax + uCooMin)/2
    "Maximum loop signal for the OA damper to be fully open"
  parameter Real uRetDamMin(unit="1")=(uHeaMax + uCooMin)/2
    "Minimum loop signal for the RA damper to be fully open"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput VOutMinSet_flow_normalized(
    final unit="1")
    "Effective minimum outdoor airflow setpoint, normalized by design minimum outdoor airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VOut_flow_normalized(
    final unit="1")
    if (minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
     or minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.SingleDamper)
    "Measured outdoor volumetric airflow rate, normalized by design minimum outdoor airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uSupFan(final unit="1")
    if (minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
     or minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure)
    "Commanded supply fan speed"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput effAbsOutAir_normalized(
    final unit="1")
    if (minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure
     and venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24)
    "Effective minimum outdoor airflow setpoint, normalized by the absolute outdoor airflow rate "
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uCO2Loo_max(
    final unit="1")
    if (have_CO2Sen and venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24)
     and minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure
    "Maximum Zone CO2 control loop"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput effDesOutAir_normalized(
    final unit="1")
    if minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure
     and venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Effective minimum outdoor airflow setpoint, normalized by the design outdoor airflow rate "
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpMinOutDam(
    final unit="Pa",
    final quantity="PressureDifference")
    if minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure
    "Measured pressure difference across the minimum outdoor air damper"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uTSup(
    final unit="1")
    "Signal for supply air temperature control (T Sup Control Loop Signal in diagram)"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature") "Outdoor air (OA) temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TAirRet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature") if (ecoHigLimCon == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.DifferentialDryBulb
     or ecoHigLimCon == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.FixedDryBulbWithDifferentialDryBulb)
    "Used only for fixed plus differential dry bulb temperature high limit cutoff"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput hAirOut(
    final unit="J/kg",
    final quantity="SpecificEnergy")
    if (ecoHigLimCon == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.DifferentialEnthalpyWithFixedDryBulb
     or ecoHigLimCon == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.FixedEnthalpyWithFixedDryBulb)
    "Outdoor air enthalpy"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput hAirRet(
    final unit="J/kg",
    final quantity="SpecificEnergy")
    if (eneStd == Buildings.Controls.OBC.ASHRAE.G36.Types.EnergyStandard.ASHRAE90_1
     and ecoHigLimCon == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.DifferentialEnthalpyWithFixedDryBulb)
    "Return air enthalpy"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SupFan
    "Supply fan status"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod
    "AHU operation mode status signal"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uFreProSta
    "Freeze protection status"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOutDam_min(
    final min=0,
    final max=1,
    final unit="1")
    "Minimum outdoor air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEnaMinOut
    "True: enable minimum outdoor air control loop"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMinOutDam(
    final min=0,
    final max=1,
    final unit="1")
    if minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
    "Minimum outdoor air flow damper commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1MinOutDam
    if minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure
    "Minimum outdoor air damper command on position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDam(
    final min=0,
    final max=1,
    final unit="1")
    "Return air damper commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRelDam(
    final min=0,
    final max=1,
    final unit="1") if buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanMeasuredAir
    "Relief air damper commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOutDam(
    final min=0,
    final max=1,
    final unit="1")
    "Outdoor air damper commanded position"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits.SeparateWithAFMS
    sepAFMS(
    final minSpe=minSpe,
    final minOAConTyp=minOAConTyp,
    final kMinOA=kMinOA,
    final TiMinOA=TiMinOA,
    final TdMinOA=TdMinOA,
    final retDamPhy_max=retDamPhy_max,
    final retDamPhy_min=retDamPhy_min,
    final outDamPhy_max=outDamPhy_max,
    final outDamPhy_min=outDamPhy_min,
    final minOutDamPhy_max=minOutDamPhy_max,
    final minOutDamPhy_min=minOutDamPhy_min)
    if minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
    "Damper position limits for units with separated minimum outdoor air damper and airflow measurement"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits.SeparateWithDP
    sepDp(
    final venStd=venStd,
    final have_CO2Sen=have_CO2Sen,
    final dpAbsMinOutDam=dpAbsMinOutDam,
    final dpDesMinOutDam=dpDesMinOutDam,
    final minSpe=minSpe,
    final dpCon=dpConTyp,
    final kDp=kDp,
    final TiDp=TiDp,
    final TdDp=TdDp,
    final retDamPhy_max=retDamPhy_max,
    final retDamPhy_min=retDamPhy_min,
    final outDamPhy_max=outDamPhy_max,
    final outDamPhy_min=outDamPhy_min)
    if minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure
    "Damper position limits for units with separated minimum outdoor air damper and differential pressure measurement"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits.Common
    damLim(
    final uRetDam_min=uRetDam_min,
    final controllerType=minOAConTyp,
    final k=kMinOA,
    final Ti=TiMinOA,
    final Td=TdMinOA,
    final retDamPhy_max=retDamPhy_max,
    final retDamPhy_min=retDamPhy_min,
    final outDamPhy_max=outDamPhy_max,
    final outDamPhy_min=outDamPhy_min)
    if minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.SingleDamper
    "Damper position limits for units with common damper"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Enable enaDis(
    final use_enthalpy=ecoHigLimCon == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.DifferentialEnthalpyWithFixedDryBulb
                       or ecoHigLimCon == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.FixedEnthalpyWithFixedDryBulb,
    final delTOutHis=delTOutHis,
    final delEntHis=delEntHis,
    final retDamFulOpeTim=retDamFulOpeTim,
    final disDel=disDel) "Enable or disable economizer"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Modulations.ReturnFan
    modRet(
    final have_dirCon=buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanDp,

    final uMin=uHeaMax,
    final uMax=uCooMin) if (buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanMeasuredAir
     or buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanDp)
    "Modulate economizer dampers position for buildings with return fan controlling pressure"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Modulations.Reliefs modRel(
    final uMin=uHeaMax,
    final uMax=uCooMin,
    final uOutDamMax=uOutDamMax,
    final uRetDamMin=uRetDamMin) if (buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefDamper
     or buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefFan
     or buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.BarometricRelief)
    "Modulate economizer dampers position for buildings with relief damper or fan controlling pressure"
  Buildings.Controls.OBC.ASHRAE.G36.Generic.AirEconomizerHighLimits ecoHigLim(
    final eneStd=eneStd,
    final ecoHigLimCon=ecoHigLimCon,
    final ashCliZon=ashCliZon,
    final tit24CliZon=tit24CliZon) "High limits"
equation
  connect(sepAFMS.VOutMinSet_flow_normalized, VOutMinSet_flow_normalized)
  connect(sepAFMS.uSupFan, uSupFan)
  connect(sepDp.dpMinOutDam, dpMinOutDam)
  connect(VOutMinSet_flow_normalized, sepDp.VOutMinSet_flow_normalized)
  connect(uSupFan, sepDp.uSupFan)
  connect(u1SupFan, sepAFMS.u1SupFan)
  connect(u1SupFan, sepDp.u1SupFan)
  connect(u1SupFan, damLim.u1SupFan)
  connect(uOpeMod, sepAFMS.uOpeMod)
  connect(uOpeMod, sepDp.uOpeMod)
  connect(uOpeMod, damLim.uOpeMod)
  connect(VOutMinSet_flow_normalized, damLim.VOutMinSet_flow_normalized)
  connect(u1SupFan, enaDis.u1SupFan)
  connect(uFreProSta, enaDis.uFreProSta)
  connect(damLim.yOutDam_min, enaDis.uOutDam_min)
  connect(damLim.yOutDam_max, enaDis.uOutDam_max)
  connect(damLim.yRetDam_min, enaDis.uRetDam_min)
  connect(damLim.yRetDam_max, enaDis.uRetDam_max)
  connect(damLim.yRetDamPhy_max, enaDis.uRetDamPhy_max)
  connect(sepDp.yOutDam_min, enaDis.uOutDam_min)
  connect(sepDp.yOutDam_max, enaDis.uOutDam_max)
  connect(sepDp.yRetDam_min, enaDis.uRetDam_min)
  connect(sepDp.yRetDam_max, enaDis.uRetDam_max)
  connect(sepDp.yRetDamPhy_max, enaDis.uRetDamPhy_max)
  connect(sepAFMS.yOutDam_min, enaDis.uOutDam_min)
  connect(sepAFMS.yOutDam_max, enaDis.uOutDam_max)
  connect(sepAFMS.yRetDam_min, enaDis.uRetDam_min)
  connect(sepAFMS.yRetDam_max, enaDis.uRetDam_max)
  connect(sepAFMS.yRetDamPhy_max, enaDis.uRetDamPhy_max)
  connect(uTSup, modRet.uTSup)
  connect(uTSup, modRel.uTSup)
  connect(damLim.yOutDam_min, modRel.uOutDam_min)
  connect(sepDp.yOutDam_min, modRel.uOutDam_min)
  connect(sepAFMS.yOutDam_min, modRel.uOutDam_min)
  connect(enaDis.yOutDam_max, modRel.uOutDam_max)
  connect(enaDis.yRetDam_max, modRel.uRetDam_max)
  connect(enaDis.yRetDam_min, modRel.uRetDam_min)
  connect(enaDis.yRetDam_max, modRet.uRetDam_max)
  connect(enaDis.yRetDam_min, modRet.uRetDam_min)
  connect(modRet.yRetDam, yRetDam)
  connect(modRel.yRetDam, yRetDam)
  connect(modRet.yOutDam, yOutDam)
  connect(modRel.yOutDam, yOutDam)
  connect(modRet.yRelDam, yRelDam)
  connect(sepAFMS.yMinOutDam, yMinOutDam)
  connect(damLim.yOutDam_min, yOutDam_min)
  connect(sepDp.yOutDam_min, yOutDam_min)
  connect(sepAFMS.yOutDam_min, yOutDam_min)
  connect(ecoHigLim.TCut, enaDis.TOutCut)
  connect(ecoHigLim.hCut, enaDis.hOutCut)
  connect(hAirRet, ecoHigLim.hRet)
  connect(TAirRet, ecoHigLim.TRet)
  connect(TOut, enaDis.TOut)
  connect(hAirOut, enaDis.hOut)
  connect(effAbsOutAir_normalized, sepDp.effAbsOutAir_normalized)
  connect(uCO2Loo_max, sepDp.uCO2Loo_max)
  connect(effDesOutAir_normalized, sepDp.effDesOutAir_normalized)
  connect(modRet.yOutDam, sepAFMS.uOutDam)
  connect(modRet.yOutDam, sepDp.uOutDam)
  connect(modRel.yOutDam, sepAFMS.uOutDam)
  connect(modRel.yOutDam, sepDp.uOutDam)
  connect(sepDp.y1MinOutDam, y1MinOutDam)
  connect(VOut_flow_normalized, sepAFMS.VOut_flow_normalized)
  connect(VOut_flow_normalized, damLim.VOut_flow_normalized)
  connect(sepAFMS.yEnaMinOut, yEnaMinOut)
  connect(sepDp.y1MinOutDam, yEnaMinOut)
  connect(damLim.yEnaMinOut, yEnaMinOut)
end Controller;


within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV;
package Economizers "Economizer control of multi zone VAV AHU"
end Economizers;


Multi zone VAV AHU economizer enable/disable switch. This is a multi zone VAV AHU economizer enable/disable sequence
based on the Section 5.16.7 of the ASHRAE Guideline 36, May 2020. Additional
conditions included in the sequence are: freeze protection (freeze protection
stage 0-3, see Section 5.16.12), supply fan status (on or off, see Section 5.16.5).

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences;
block Enable "Multi zone VAV AHU economizer enable/disable switch"

  parameter Boolean use_enthalpy = true
    "Set to true to evaluate outdoor air (OA) enthalpy in addition to temperature"
  parameter Real delTOutHis(
    final unit="K",
    final displayUnit="K",
    final quantity="TemperatureDifference")=1
    "Delta between the temperature hysteresis high and low limit"
  parameter Real delEntHis(
    final unit="J/kg",
    final quantity="SpecificEnergy")=1000
    "Delta between the enthalpy hysteresis high and low limits"
  parameter Real retDamFulOpeTim(
    final unit="s",
    final quantity="Time")=180
    "Time period to keep RA damper fully open before releasing it for minimum outdoor airflow control
    at disable to avoid pressure fluctuations"
  parameter Real disDel(
    final unit="s",
    final quantity="Time")=15
    "Short time delay before closing the OA damper at disable to avoid pressure fluctuations"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut(
    final unit="K",
    final displayUnit="degC",
    final quantity = "ThermodynamicTemperature")
    "Outdoor air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput hOut(
    final unit="J/kg",
    final quantity="SpecificEnergy") if use_enthalpy
    "Outdoor air enthalpy"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TOutCut(
    final unit="K",
    final displayUnit="degC",
    final quantity = "ThermodynamicTemperature")
    "OA temperature high limit cutoff. For differential dry bulb temperature condition use return air temperature measurement"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput hOutCut(
    final unit="J/kg",
    final quantity="SpecificEnergy") if use_enthalpy
    "OA enthalpy high limit cutoff. For differential enthalpy use return air enthalpy measurement"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput uOutDam_min(
    final unit="1",
    final min=0,
    final max=1)
    "Minimum outdoor air damper position, output from damper position limits sequence"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uOutDam_max(
    final unit="1",
    final min=0,
    final max=1)
    "Maximum outdoor air damper position, output from damper position limits sequence"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uRetDam_max(
    final unit="1",
    final min=0,
    final max=1)
    "Maximum return air damper position, output from damper position limits sequence"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uRetDam_min(
    final unit="1",
    final min=0,
    final max=1)
    "Minimum return air damper position, output from damper position limits sequence"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uRetDamPhy_max(
    final unit="1",
    final min=0,
    final max=1)
    "Physical maximum return air damper position, output from damper position limits sequence"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SupFan
    "Supply fan proven on"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uFreProSta "Freeze protection stage status signal"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOutDam_max(
    final unit="1",
    final min=0,
    final max=1)
    "Maximum outdoor air damper position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDam_min(
    final unit="1",
    final min=0,
    final max=1)
    "Minimum return air damper position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDam_max(
    final unit="1",
    final min=0,
    final max=1)
    "Maximum return air damper position"

  Buildings.Controls.OBC.CDL.Logical.TrueFalseHold truFalHol(
    final trueHoldDuration=600)
    "Economizer should not be enabled or disabled within 10 minutes of change"
  Buildings.Controls.OBC.CDL.Logical.And andEnaDis
    "Check freeze protection stage and zone state"

protected
  final parameter Real TOutHigLimCutHig(
    final unit="K",
    final displayUnit="K",
    final quantity="TemperatureDifference")= 0
    "Hysteresis high limit cutoff";
  final parameter Real TOutHigLimCutLow = TOutHigLimCutHig - delTOutHis
    "Hysteresis low limit cutoff";
  final parameter Real hOutHigLimCutHig(
    final unit="J/kg",
    final quantity="SpecificEnergy")= 0
    "Hysteresis block high limit cutoff";
  final parameter Real hOutHigLimCutLow = hOutHigLimCutHig - delEntHis
    "Hysteresis block low limit cutoff";

  Buildings.Controls.OBC.CDL.Reals.Subtract sub2
    if use_enthalpy "Add block determines difference between hOut and hOutCut"
  Buildings.Controls.OBC.CDL.Reals.Subtract sub1
    "Add block determines difference between TOut and TOutCut"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysOutTem(
    final uLow=TOutHigLimCutLow,
    final uHigh=TOutHigLimCutHig)
    "Outdoor air temperature hysteresis for both fixed and differential dry bulb temperature cutoff conditions"
  Buildings.Controls.OBC.CDL.Reals.Hysteresis hysOutEnt(
    final uLow=hOutHigLimCutLow,
    final uHigh=hOutHigLimCutHig) if use_enthalpy
    "Outdoor air enthalpy hysteresis for both fixed and differential enthalpy cutoff conditions"
  Buildings.Controls.OBC.CDL.Reals.Switch outDamSwitch
    "Set maximum OA damper position to minimum at disable (after a given time delay)"
  Buildings.Controls.OBC.CDL.Reals.Switch retDamSwitch "Set minimum RA damper position to maximum at disable"
  Buildings.Controls.OBC.CDL.Reals.Switch maxRetDamSwitch
    "Keep maximum RA damper position at physical maximum for a short time period after disable signal"
  Buildings.Controls.OBC.CDL.Reals.Switch minRetDamSwitch
    "Keep minimum RA damper position at physical maximum for a short time period after disable"
  Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not that starts the timer at disable signal "
  Buildings.Controls.OBC.CDL.Logical.And  and2 "Logical and"
  Buildings.Controls.OBC.CDL.Logical.And and1 "Check supply fan status"
  Buildings.Controls.OBC.CDL.Logical.And and3
    "Check if delay time has been passed after economizer being disabled"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu
    "Logical block to check if the freeze protection is deactivated"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay delOutDamOsc(
    final delayTime=disDel)
    "Small delay before closing the outdoor air damper to avoid pressure fluctuations"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay delRetDam(
    final delayTime=retDamFulOpeTim)
    "Keep return damper open to its physical maximum for a short period of time before closing the outdoor air damper and resuming the maximum return air damper position, per G36 Part N7"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.FreezeProtectionStages.stage0)
    "Integer constant, stage 0"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant entSubst1(
    final k=false) if not use_enthalpy
    "Deactivates outdoor air enthalpy condition if there is no enthalpy sensor"
  Buildings.Controls.OBC.CDL.Logical.Or or2
    "Check if either the temperature or the enthalpy condition is satisfied"
equation
  connect(TOut, sub1.u1)
  connect(TOutCut, sub1.u2)
  connect(sub1.y, hysOutTem.u)
  connect(hOut, sub2.u1)
  connect(hOutCut, sub2.u2)
  connect(sub2.y, hysOutEnt.u)
  connect(uOutDam_min, outDamSwitch.u1)
  connect(uOutDam_max, outDamSwitch.u3)
  connect(uRetDamPhy_max, maxRetDamSwitch.u1)
  connect(uRetDam_max, maxRetDamSwitch.u3)
  connect(andEnaDis.y, not2.u)
  connect(maxRetDamSwitch.y, yRetDam_max)
  connect(and2.y, maxRetDamSwitch.u2)
  connect(and2.y, minRetDamSwitch.u2)
  connect(not2.y, retDamSwitch.u2)
  connect(uRetDam_max, retDamSwitch.u1)
  connect(uRetDam_min, retDamSwitch.u3)
  connect(retDamSwitch.y, minRetDamSwitch.u3)
  connect(uRetDamPhy_max, minRetDamSwitch.u1)
  connect(truFalHol.y, and1.u1)
  connect(and1.y, andEnaDis.u1)
  connect(u1SupFan, and1.u2)
  connect(outDamSwitch.u2, and3.y)
  connect(not2.y, and3.u1)
  connect(and2.u1, not2.y)
  connect(and3.u2, delOutDamOsc.y)
  connect(delOutDamOsc.u, not2.y)
  connect(not2.y, delRetDam.u)
  connect(delRetDam.y, not1.u)
  connect(not1.y, and2.u2)
  connect(uFreProSta, intEqu.u1)
  connect(conInt.y, intEqu.u2)
  connect(intEqu.y, andEnaDis.u2)
  connect(outDamSwitch.y, yOutDam_max)
  connect(minRetDamSwitch.y, yRetDam_min)
  connect(or2.y, truFalHol.u)
  connect(hysOutTem.y, or2.u1)
  connect(hysOutEnt.y, or2.u2)
  connect(entSubst1.y, or2.u2)
end Enable;


Subsequences for economizer control

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers;
package Subsequences "Subsequences for economizer control"
end Subsequences;


Outdoor air and return air damper position limits for units with common damper. This block models the multi zone VAV AHU minimum outdoor air control with a single
common damper for minimum outdoor air and economizer functions based on outdoor airflow
measurement, designed in line with the Section 5.16.6 of the ASHRAE Guideline 36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits;
block Common
  "Outdoor air and return air damper position limits for units with common damper"

  parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller"

  parameter Real k(
    final unit="1")=0.05 "Gain of damper limit controller"

  parameter Real Ti(
    final unit="s",
    final quantity="Time")=120
    "Time constant of damper limit controller integrator block"

  parameter Real Td(
    final unit="s",
    final quantity="Time")=0.1
    "Time constant of damper limit controller derivative block"

  parameter Real uRetDam_min(
    final min=yMin,
    final max=yMax,
    final unit="1") = 0.5
    "Loop signal value to start decreasing the maximum return air damper position"

  parameter Real retDamPhy_max(
    final min=0,
    final max=1,
    final unit="1") = 1.0
    "Physically fixed maximum position of the return air damper"
  parameter Real retDamPhy_min(
    final min=0,
    final max=1,
    final unit="1") = 0.0
    "Physically fixed minimum position of the return air damper"
  parameter Real outDamPhy_max(
    final min=0,
    final max=1,
    final unit="1") = 1.0
    "Physically fixed maximum position of the outdoor air damper"
  parameter Real outDamPhy_min(
    final min=0,
    final max=1,
    final unit="1") = 0.0
    "Physically fixed minimum position of the outdoor air damper"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput VOut_flow_normalized(
   final unit="1")
    "Measured outdoor volumetric airflow rate, normalized by design minimum outdoor airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VOutMinSet_flow_normalized(
    final unit="1")
    "Effective minimum outdoor airflow setpoint, normalized by design minimum outdoor airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod
    "AHU operation mode status signal"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SupFan
    "Supply fan proven on"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOutDam_min(
    final min=outDamPhy_min,
    final max=outDamPhy_max,
    final unit="1")
    "Minimum outdoor air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOutDam_max(
    final min=outDamPhy_min,
    final max=outDamPhy_max,
    final unit="1")
    "Maximum outdoor air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDam_min(
    final min=retDamPhy_min,
    final max=retDamPhy_max,
    final unit="1")
    "Minimum return air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDam_max(
    final min=retDamPhy_min,
    final max=retDamPhy_max,
    final unit="1")
    "Maximum return air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDamPhy_max(
    final min=0,
    final max=1,
    final unit="1")
    "Physical maximum return air damper position limit. Required as an input for the economizer enable disable sequence"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEnaMinOut
    "True: enable minimum outdoor air control loop"

  Buildings.Controls.OBC.CDL.Reals.PIDWithReset damLimCon(
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti,
    final Td=Td,
    final yMax=yMax,
    final yMin=yMin)
    "Damper position limit controller"

protected
  parameter Real yMin=0 "Lower limit of control loop signal";
  parameter Real yMax=1 "Upper limit of control loop signal";
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant outDamPhyPosMinSig(
    final k=outDamPhy_min)
    "Physically fixed minimum position of the outdoor air damper. This is the initial position of the economizer damper"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant outDamPhyPosMaxSig(
    final k=outDamPhy_max)
    "Physically fixed maximum position of the outdoor air damper."
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant retDamPhyPosMinSig(
    final k=retDamPhy_min)
    "Physically fixed minimum position of the return air damper"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant retDamPhyPosMaxSig(
    final k=retDamPhy_max)
    "Physically fixed maximum position of the return air damper. This is the initial condition of the return air damper"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minSigLim(
    final k=yMin)
    "Equals minimum controller output signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxSigLim(
    final k=yMax)
    "Equals maximum controller output signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant sigFraForOutDam(
    final k=uRetDam_min) "Equals the fraction of the control loop signal below which the outdoor air damper
    limit gets modulated and above which the return air damper limit gets modulated"
  Buildings.Controls.OBC.CDL.Reals.Line minOutDam(
    final limitBelow=true,
    final limitAbove=true)
    "Linear mapping of the outdoor air damper position to the control signal"
  Buildings.Controls.OBC.CDL.Reals.Line minRetDam(
    final limitBelow=true,
    final limitAbove=true)
    "Linear mapping of the return air damper position to the control signal"
  Buildings.Controls.OBC.CDL.Reals.Switch retDamPosMinSwitch
    "A switch to deactivate the return air damper minimal outdoor airflow control"
  Buildings.Controls.OBC.CDL.Reals.Switch outDamPosMaxSwitch
    "A switch to deactivate the outdoor air damper minimal outdoor airflow control"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "Logical not block"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied)
    "Occupied mode index"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu
    "Check if operation mode is occupied"
  Buildings.Controls.OBC.CDL.Logical.And and3 "Logical and"

equation
  connect(minRetDam.y, yRetDam_max)
  connect(retDamPosMinSwitch.y, minRetDam.f2)
  connect(sigFraForOutDam.y, minRetDam.x1)
  connect(maxSigLim.y, minRetDam.x2)
  connect(VOut_flow_normalized, damLimCon.u_m)
  connect(VOutMinSet_flow_normalized, damLimCon.u_s)
  connect(damLimCon.y, minRetDam.u)
  connect(outDamPosMaxSwitch.y, minOutDam.f2)
  connect(minSigLim.y, minOutDam.x1)
  connect(sigFraForOutDam.y, minOutDam.x2)
  connect(damLimCon.y, minOutDam.u)
  connect(outDamPosMaxSwitch.y, yOutDam_max)
  connect(minOutDam.y, yOutDam_min)
  connect(retDamPhyPosMaxSig.y, retDamPosMinSwitch.u1)
  connect(retDamPhyPosMaxSig.y, minRetDam.f1)
  connect(retDamPhyPosMinSig.y, retDamPosMinSwitch.u3)
  connect(outDamPhyPosMaxSig.y, outDamPosMaxSwitch.u3)
  connect(outDamPhyPosMinSig.y, outDamPosMaxSwitch.u1)
  connect(outDamPhyPosMinSig.y, minOutDam.f1)
  connect(not1.y, retDamPosMinSwitch.u2)
  connect(not1.y, outDamPosMaxSwitch.u2)
  connect(retDamPosMinSwitch.y, yRetDam_min)
  connect(retDamPhyPosMaxSig.y, yRetDamPhy_max)
  connect(uOpeMod, intEqu.u1)
  connect(conInt1.y, intEqu.u2)
  connect(damLimCon.trigger, u1SupFan)
  connect(and3.y, not1.u)
  connect(intEqu.y, and3.u2)
  connect(u1SupFan, and3.u1)
  connect(and3.y, yEnaMinOut)
end Common;


within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences;
package Limits "Package of sequences to calculate the damper position limits of the economizer"
end Limits;


Outdoor air and return air damper position limits for units with separated minimum outdoor air damper and airflow measurement. Block that outputs the position limits of the return and outdoor air damper for units
with a separated minimum outdoor air damper and airflow measurement.
It is implemented according to Section 5.16.5 of the ASHRAE Guideline 36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits;
block SeparateWithAFMS
  "Outdoor air and return air damper position limits for units with separated minimum outdoor air damper and airflow measurement"

  parameter Real minSpe(
     final unit="1",
     final min=0,
     final max=1)
     "Minimum supply fan speed";
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController minOAConTyp=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of minimum outdoor air controller"
  parameter Real kMinOA(
    final unit="1")=1 "Gain of controller"
  parameter Real TiMinOA(
    final unit="s",
    final quantity="Time")=0.5 "Time constant of integrator block"
  parameter Real TdMinOA(
    final unit="s",
    final quantity="Time")=0.1 "Time constant of derivative block"

  parameter Real retDamPhy_max(
    final min=0,
    final max=1,
    final unit="1") = 1 "Physically fixed maximum position of the return air damper"
  parameter Real retDamPhy_min(
    final min=0,
    final max=1,
    final unit="1") = 0
    "Physically fixed minimum position of the return air damper"
  parameter Real outDamPhy_max(
    final min=0,
    final max=1,
    final unit="1") = 1
    "Physically fixed maximum position of the outdoor air damper"
  parameter Real outDamPhy_min(
    final min=0,
    final max=1,
    final unit="1") = 0
    "Physically fixed minimum position of the outdoor air damper"
  parameter Real minOutDamPhy_max(
    final min=0,
    final max=1,
    final unit="1") = 1
    "Physically fixed maximum position of the minimum outdoor air damper"
  parameter Real minOutDamPhy_min(
    final min=0,
    final max=1,
    final unit="1") = 0
    "Physically fixed minimum position of the minimum outdoor air damper"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput VOutMinSet_flow_normalized(
    final unit="1")
    "Effective minimum outdoor airflow setpoint, normalized by design minimum outdoor airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VOut_flow_normalized(
    final unit="1")
    "Measured outdoor volumetric airflow rate, normalized by design minimum outdoor airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SupFan
    "Supply fan proven on"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod
    "AHU operation mode status signal"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uOutDam(
    final min=0,
    final max=1,
    final unit="1") "Economizer outdoor air damper commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uSupFan(
    final min=0,
    final max=1,
    final unit="1")
    "Commanded supply fan speed"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMinOutDam(
    final min=0,
    final max=1,
    final unit="1")
    "Minimum outdoor air damper commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput yEnaMinOut
    "True: enable minimum outdoor air control loop"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOutDam_min(
    final min=outDamPhy_min,
    final max=outDamPhy_max,
    final unit="1") "Physically minimum outdoor air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOutDam_max(
    final min=outDamPhy_min,
    final max=outDamPhy_max,
    final unit="1")
    "Physically maximum outdoor air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDam_min(
    final min=retDamPhy_min,
    final max=retDamPhy_max,
    final unit="1")
    "Minimum return air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDam_max(
    final min=retDamPhy_min,
    final max=retDamPhy_max,
    final unit="1")
    "Maximum return air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDamPhy_max(
    final min=0,
    final max=1,
    final unit="1")
    "Physical maximum return air damper position limit. Required as an input for the economizer enable disable sequence"

  Buildings.Controls.OBC.CDL.Reals.PIDWithReset conMinOA(
    final controllerType=minOAConTyp,
    final k=kMinOA,
    final Ti=TiMinOA,
    final Td=TdMinOA,
    final yMax=minOutDamPhy_max,
    final yMin=minOutDamPhy_min)
    "Minimum outdoor air flow control"

protected
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied)
    "Occupied mode index"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu
    "Check if operation mode is occupied"
  Buildings.Controls.OBC.CDL.Logical.And enaMinCon
    "Check if the minimum outdoor air control loop should be enabled"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(
    final k=0) "Constant"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(
    final k=0.5) "Constant"
  Buildings.Controls.OBC.CDL.Reals.Line minOutDamPos(
    final limitBelow=true,
    final limitAbove=true)
    "Minimum outdoor air damper position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minOutDamPhyPosMinSig(
    final k=minOutDamPhy_min)
    "Physically fixed minimum position of the minimum outdoor air damper. This is the initial position of the economizer damper"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minOutDamPhyPosMaxSig(
    final k=minOutDamPhy_max)
    "Physically fixed maximum position of the minimum outdoor air damper"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(
    final k=1) "Constant one"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1(
    final k=0.05) "Constant"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con2(
    final k=0.8) "Constant"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minFanSpe(
    final k=minSpe) "Minimum fan speed"
  Buildings.Controls.OBC.CDL.Reals.Line moaP(
    final limitBelow=true,
    final limitAbove=true)
    "Linear mapping of the supply fan speed to the control signal"
  Buildings.Controls.OBC.CDL.Reals.Less les(
    final h=0.05)
    "Check if economizer outdoor air damper is less than projected position"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr(
    final t=0.98,
    final h=0.01)
    "Check if the minimum outdoor air damper position is fully open"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai(
    final k=1.1)
    "Projected position with a gain factor"
  Buildings.Controls.OBC.CDL.Reals.Greater gre(
    final h=0.05)
    "Check if the economizer outdoor air damper is greater than threshold"
  Buildings.Controls.OBC.CDL.Logical.And enaRetDamMin
    "Enable return air damper minimum outdoor air control"
  Buildings.Controls.OBC.CDL.Logical.Latch enaDis
    "Enable or disable return air damper minimum outdoor air control"
  Buildings.Controls.OBC.CDL.Logical.Not cloMinDam
    "Check if the minimum outdoor air damper is closed"
  Buildings.Controls.OBC.CDL.Logical.Or disRetDamMin
    "Disable return air damper minimum outdoor air control"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant outDamPhyPosMinSig(
    final k=outDamPhy_min)
    "Physically fixed minimum position of the outdoor air damper. This is the initial position of the economizer damper"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant outDamPhyPosMaxSig(
    final k=outDamPhy_max)
    "Physically fixed maximum position of the outdoor air damper."
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant retDamPhyPosMinSig(
    final k=retDamPhy_min)
    "Physically fixed minimum position of the return air damper"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant retDamPhyPosMaxSig(
    final k=retDamPhy_max)
    "Physically fixed maximum position of the return air damper. This is the initial condition of the return air damper"
  Buildings.Controls.OBC.CDL.Reals.Switch retDamPosMinSwi
    "A switch to deactivate the return air damper minimal outdoor airflow control"
  Buildings.Controls.OBC.CDL.Reals.Switch retDamPosMaxSwi
    "A switch to deactivate the return air damper minimal outdoor airflow control"
  Buildings.Controls.OBC.CDL.Reals.Line maxRetDamPos(
    final limitBelow=true,
    final limitAbove=true)
    "Maximum return air damper position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con3(
    final k=0.5) "Constant"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con4(
    final k=1) "Constant"

equation
  connect(uOpeMod, intEqu.u1)
  connect(conInt1.y, intEqu.u2)
  connect(intEqu.y, enaMinCon.u2)
  connect(VOutMinSet_flow_normalized,conMinOA. u_s)
  connect(VOut_flow_normalized,conMinOA. u_m)
  connect(enaMinCon.y,conMinOA. trigger)
  connect(zer.y, minOutDamPos.x1)
  connect(conMinOA.y, minOutDamPos.u)
  connect(minOutDamPhyPosMinSig.y, minOutDamPos.f1)
  connect(con.y, minOutDamPos.x2)
  connect(minOutDamPhyPosMaxSig.y, minOutDamPos.f2)
  connect(minFanSpe.y, moaP.x1)
  connect(con2.y, moaP.f1)
  connect(uSupFan, moaP.u)
  connect(con1.y, moaP.f2)
  connect(one.y, moaP.x2)
  connect(uOutDam, les.u1)
  connect(moaP.y, les.u2)
  connect(moaP.y, gai.u)
  connect(uOutDam, gre.u1)
  connect(gai.y, gre.u2)
  connect(minOutDamPos.y, greThr.u)
  connect(les.y, enaRetDamMin.u2)
  connect(greThr.y, enaRetDamMin.u1)
  connect(greThr.y, cloMinDam.u)
  connect(cloMinDam.y, disRetDamMin.u1)
  connect(gre.y, disRetDamMin.u2)
  connect(enaRetDamMin.y, enaDis.u)
  connect(disRetDamMin.y, enaDis.clr)
  connect(outDamPhyPosMinSig.y, yOutDam_min)
  connect(outDamPhyPosMaxSig.y, yOutDam_max)
  connect(retDamPhyPosMaxSig.y, yRetDamPhy_max)
  connect(retDamPosMinSwi.y, yRetDam_min)
  connect(con3.y, maxRetDamPos.x1)
  connect(con4.y, maxRetDamPos.x2)
  connect(retDamPhyPosMinSig.y, maxRetDamPos.f2)
  connect(enaDis.y, retDamPosMaxSwi.u2)
  connect(maxRetDamPos.y, retDamPosMaxSwi.u1)
  connect(retDamPhyPosMinSig.y, retDamPosMaxSwi.u3)
  connect(retDamPosMaxSwi.y, yRetDam_max)
  connect(enaDis.y, retDamPosMinSwi.u2)
  connect(retDamPhyPosMinSig.y, retDamPosMinSwi.u1)
  connect(retDamPhyPosMaxSig.y, maxRetDamPos.f1)
  connect(retDamPhyPosMaxSig.y, retDamPosMinSwi.u3)
  connect(conMinOA.y, maxRetDamPos.u)
  connect(minOutDamPos.y, yMinOutDam)
  connect(u1SupFan, enaMinCon.u1)
  connect(enaMinCon.y, yEnaMinOut)
end SeparateWithAFMS;


Outdoor air and return air damper position limits for units with separated minimum outdoor air damper and differential pressure control. Block that outputs the position limits of the return and outdoor air damper for units
with a separated minimum outdoor air damper and differential pressure control.
It is implemented according to Section 5.16.4 of the ASHRAE Guideline 36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits;
block SeparateWithDP
  "Outdoor air and return air damper position limits for units with separated minimum outdoor air damper and differential pressure control"

  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard venStd
    "Ventilation standard, ASHRAE 62.1 or Title 24";
  parameter Boolean have_CO2Sen=false
    "True: some zones have CO2 sensor"
  parameter Real dpAbsMinOutDam(
    unit="Pa",
    displayUnit="Pa")=5
    "Absolute minimum pressure difference across the minimum outdoor air damper. It provides the absolute minimum outdoor airflow"
  parameter Real dpDesMinOutDam(
    unit="Pa",
    displayUnit="Pa")=20
    "Design minimum pressure difference across the minimum outdoor air damper. It provides the design minimum outdoor airflow"
  parameter Real minSpe(unit="1")
     "Minimum supply fan speed"
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController dpCon=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of differential pressure setpoint controller"
  parameter Real kDp(unit="1")=1 "Gain of controller"
  parameter Real TiDp(unit="s")=0.5
    "Time constant of integrator block"
  parameter Real TdDp(unit="s")=0.1
    "Time constant of derivative block"
  parameter Real retDamPhy_max(unit="1")=1
    "Physically fixed maximum position of the return air damper"
  parameter Real retDamPhy_min(unit="1")=0
    "Physically fixed minimum position of the return air damper"
  parameter Real outDamPhy_max(unit="1")=1
    "Physically fixed maximum position of the outdoor air damper"
  parameter Real outDamPhy_min(unit="1")=0
    "Physically fixed minimum position of the outdoor air damper"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput effAbsOutAir_normalized(
    final unit="1")
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Effective minimum outdoor airflow setpoint, normalized by the absolute outdoor airflow rate "
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uCO2Loo_max(final unit="1")
    if have_CO2Sen and venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Maximum zone CO2 control loop"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput effDesOutAir_normalized(
    final unit="1")
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Effective minimum outdoor airflow setpoint, normalized by the design outdoor airflow rate "
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpMinOutDam(
    final unit="Pa",
    displayUnit="Pa",
    final quantity="PressureDifference")
    "Measured pressure difference across the minimum outdoor air damper"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VOutMinSet_flow_normalized(
    final unit="1")
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1
    "Effective minimum outdoor airflow setpoint, normalized by design minimum outdoor airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SupFan
    "Supply fan proven on"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod
    "AHU operation mode status signal"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uOutDam(
    final min=0,
    final max=1,
    final unit="1")
    "Economizer outdoor air damper commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uSupFan(
    final min=0,
    final max=1,
    final unit="1")
    "Commanded supply fan speed"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1MinOutDam
    "Status of minimum outdoor air damper position, true means it's open"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOutDam_min(
    final min=outDamPhy_min,
    final max=outDamPhy_max,
    final unit="1") "Physically minimum outdoor air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yOutDam_max(
    final min=outDamPhy_min,
    final max=outDamPhy_max,
    final unit="1") "Physically maximum outdoor air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDam_min(
    final min=retDamPhy_min,
    final max=retDamPhy_max,
    final unit="1")
    "Minimum return air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDam_max(
    final min=retDamPhy_min,
    final max=retDamPhy_max,
    final unit="1")
    "Maximum return air damper position limit"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetDamPhy_max(
    final min=0,
    final max=1,
    final unit="1")
    "Physical maximum return air damper position limit. Required as an input for the economizer enable disable sequence"
  Buildings.Controls.OBC.CDL.Reals.Multiply minDp if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1
    "Minimum pressure difference setpoint when complying with ASHRAE 62.1"
  Buildings.Controls.OBC.CDL.Reals.PIDWithReset maxRetDam(
    final controllerType=dpCon,
    final k=kDp,
    final Ti=TiDp,
    final Td=TdDp) "Maximum return air damper position"

protected
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minDesDp(
    final k=dpDesMinOutDam)
    "Design minimum outdoor air damper pressure difference"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1
    "Square of the normalized minimum airflow"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr(
    final h=1)
    "Check if the minimum pressure difference setpoint is greater than zero"
  Buildings.Controls.OBC.CDL.Reals.Less les(
    final h=0.05)
    "Check if economizer outdoor air damper is less than projected position"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai(
    final k=1.1)
    "Projected position with a gain factor"
  Buildings.Controls.OBC.CDL.Reals.Greater gre(
    final h=0.05)
    "Check if the economizer outdoor air damper is greater than threshold"
  Buildings.Controls.OBC.CDL.Logical.Latch enaDis
    "Enable or disable return air damper minimum outdoor air control"
  Buildings.Controls.OBC.CDL.Logical.And enaRetDamMin
    "Enable return air damper minimum outdoor air control"
  Buildings.Controls.OBC.CDL.Logical.Or disRetDamMin
    "Disable return air damper minimum outdoor air control"
  Buildings.Controls.OBC.CDL.Logical.Not disMinDam "Check if the minimum outdoor air damper is closed"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied)
    "Occupied mode index"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu
    "Check if operation mode is occupied"
  Buildings.Controls.OBC.CDL.Logical.And enaMinDam1
    "Check if the minimum outdoor air damper should be enabled, one of two stacked And blocks"
  Buildings.Controls.OBC.CDL.Logical.And enaMinDam2
    "Check if the minimum outdoor air damper should be enabled, one of two stacked And blocks"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(
    final k=1) "Constant"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minFanSpe(
    final k=minSpe) "Minimum fan speed"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(
    final k=0.05) "Constant"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1(
    final k=0.8) "Constant"
  Buildings.Controls.OBC.CDL.Reals.Line moaP(
    final limitBelow=true,
    final limitAbove=true)
    "Linear mapping of the supply fan speed to the control signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant outDamPhyPosMinSig(
    final k=outDamPhy_min)
    "Physically fixed minimum position of the outdoor air damper. This is the initial position of the economizer damper"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant outDamPhyPosMaxSig(
    final k=outDamPhy_max)
    "Physically fixed maximum position of the outdoor air damper."
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant retDamPhyPosMinSig(
    final k=retDamPhy_min)
    "Physically fixed minimum position of the return air damper"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant retDamPhyPosMaxSig(
    final k=retDamPhy_max)
    "Physically fixed maximum position of the return air damper. This is the initial condition of the return air damper"
  Buildings.Controls.OBC.CDL.Reals.Switch retDamPosMaxSwi
    "A switch to deactivate the return air damper maximum outdoor airflow control"
  Buildings.Controls.OBC.CDL.Reals.Switch retDamPosMinSwi
    "A switch to deactivate the return air damper minimal outdoor airflow control"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro1
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Square of the normalized minimum airflow"
  Buildings.Controls.OBC.CDL.Reals.Multiply  pro2
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Square of the normalized minimum airflow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minAbsDp(
    final k=dpAbsMinOutDam)
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Absolute minimum outdoor air damper pressure difference"
  Buildings.Controls.OBC.CDL.Reals.Line minDp1(
    final limitAbove=true)
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Minimum pressure difference setpoint when complying with Title 24"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one1(
    final k=1)
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Design fan speed"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant hal(
    final k=0.5)
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Constant"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one2(
    final k=1)
    if not have_CO2Sen and venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Design fan speed"
  Buildings.Controls.OBC.CDL.Reals.Multiply actAbsMinDp
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Active absolute minimum pressure difference setpoint"
  Buildings.Controls.OBC.CDL.Reals.Multiply actDesMinDp
    if venStd == Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Active design minimum pressure difference setpoint"
equation
  connect(VOutMinSet_flow_normalized, pro.u1)
  connect(VOutMinSet_flow_normalized, pro.u2)
  connect(uOpeMod, intEqu.u1)
  connect(conInt1.y, intEqu.u2)
  connect(minDp.y, greThr.u)
  connect(minFanSpe.y, moaP.x1)
  connect(con1.y, moaP.f1)
  connect(con.y, moaP.f2)
  connect(one.y, moaP.x2)
  connect(uSupFan, moaP.u)
  connect(uOutDam, les.u1)
  connect(moaP.y, les.u2)
  connect(uOutDam, gre.u1)
  connect(gai.y, gre.u2)
  connect(moaP.y, gai.u)
  connect(enaMinDam2.y, enaRetDamMin.u1)
  connect(les.y, enaRetDamMin.u2)
  connect(enaRetDamMin.y, enaDis.u)
  connect(enaMinDam2.y, disMinDam.u)
  connect(disMinDam.y, disRetDamMin.u1)
  connect(gre.y, disRetDamMin.u2)
  connect(disRetDamMin.y, enaDis.clr)
  connect(minDp.y, maxRetDam.u_s)
  connect(dpMinOutDam, maxRetDam.u_m)
  connect(enaDis.y, maxRetDam.trigger)
  connect(retDamPhyPosMaxSig.y, yRetDamPhy_max)
  connect(enaDis.y, retDamPosMaxSwi.u2)
  connect(maxRetDam.y, retDamPosMaxSwi.u1)
  connect(retDamPosMaxSwi.y, yRetDam_max)
  connect(retDamPhyPosMaxSig.y, retDamPosMaxSwi.u3)
  connect(enaDis.y, retDamPosMinSwi.u2)
  connect(retDamPhyPosMinSig.y, retDamPosMinSwi.u1)
  connect(retDamPhyPosMaxSig.y, retDamPosMinSwi.u3)
  connect(retDamPosMinSwi.y, yRetDam_min)
  connect(outDamPhyPosMinSig.y, yOutDam_min)
  connect(outDamPhyPosMaxSig.y, yOutDam_max)
  connect(enaMinDam2.y, y1MinOutDam)
  connect(effAbsOutAir_normalized, pro1.u1)
  connect(effAbsOutAir_normalized, pro1.u2)
  connect(effDesOutAir_normalized, pro2.u1)
  connect(effDesOutAir_normalized, pro2.u2)
  connect(pro1.y, actAbsMinDp.u2)
  connect(minAbsDp.y, actAbsMinDp.u1)
  connect(minDesDp.y, actDesMinDp.u2)
  connect(pro2.y, actDesMinDp.u1)
  connect(pro.y, minDp.u2)
  connect(minDesDp.y, minDp.u1)
  connect(uCO2Loo_max, minDp1.u)
  connect(actAbsMinDp.y, minDp1.f1)
  connect(actDesMinDp.y, minDp1.f2)
  connect(hal.y, minDp1.x1)
  connect(one1.y, minDp1.x2)
  connect(minDp1.y, maxRetDam.u_s)
  connect(minDp1.y, greThr.u)
  connect(one2.y, minDp1.u)
  connect(intEqu.y, enaMinDam1.u2)
  connect(u1SupFan, enaMinDam1.u1)
  connect(greThr.y, enaMinDam2.u1)
  connect(enaMinDam1.y, enaMinDam2.u2)
end SeparateWithDP;


Validation model for the multi zone VAV AHU minimum outdoor air control - damper position limits. This example validates enable/disable conditions for

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits.Common
for the following input signals: u1SupFan, uFreProSta, uOpeMod.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits.Validation;
model Common_LoopDisable
  "Validation model for the multi zone VAV AHU minimum outdoor air control - damper position limits"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant VOutMinSet_flow(
    final k=VOutSet_flow)
    "Outdoor airflow rate setpoint, 15cfm/occupant and 100 occupants"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant VOutMinSet1_flow(
    final k=VOutSet_flow)
    "Outdoor airflow rate setpoint, 15cfm/occupant and 100 occupants"

  // Fan Status
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant fanSta(
    final k=false) "Fan is off"

  // Operation Mode
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant opeMod1(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.warmUp)
    "AHU operation mode is NOT Occupied"

  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp VOut_flow(
    final duration=1800,
    final offset=minVOutSet_flow,
    final height=incVOutSet_flow) "Measured outdoor airflow rate"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp VOut1_flow(
    final duration=1800,
    final offset=minVOutSet_flow,
    final height=incVOutSet_flow)
    "Measured outdoor airflow rate"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits.Common damLim
    "Multi zone VAV AHU minimum outdoor air control - damper position limits"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits.Common damLim1
    "Multi zone VAV AHU minimum outdoor air control - damper position limits"

protected
  final parameter Real VOutSet_flow(
    final unit="m3/s",
    final quantity="VolumeFlowRate")=0.71
    "Example volumetric airflow setpoint, 15cfm/occupant, 100 occupants";
  final parameter Real minVOutSet_flow(
    final unit="m3/s",
    final quantity="VolumeFlowRate")=0.61
    "Volumetric airflow sensor output, minimum value in the example";
  final parameter Real incVOutSet_flow(
    final unit="m3/s",
    final quantity="VolumeFlowRate")=0.2
    "Maximum increase in airflow volume during the example simulation";

  Buildings.Controls.OBC.CDL.Integers.Sources.Constant opeMod(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied)
    "AHU operation mode is Occupied"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant fanStatus1(
    final k=true) "Fan is on"

equation
  connect(VOut_flow.y, damLim.VOut_flow_normalized)
  connect(VOutMinSet_flow.y, damLim.VOutMinSet_flow_normalized)
  connect(fanSta.y, damLim.u1SupFan)
  connect(VOut1_flow.y, damLim1.VOut_flow_normalized)
  connect(VOutMinSet1_flow.y, damLim1.VOutMinSet_flow_normalized)
  connect(fanStatus1.y, damLim1.u1SupFan)
  connect(opeMod.y, damLim.uOpeMod)
  connect(opeMod1.y, damLim1.uOpeMod)
end Common_LoopDisable;


Validation model for the multi zone VAV AHU minimum outdoor air control - damper position limits. This example validates

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits.Common
for the following control signals: VOut_flow, VOutMinSet_flow. The control loop is always enabled in this
example.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits.Validation;
model Common_VOut_flow
  "Validation model for the multi zone VAV AHU minimum outdoor air control - damper position limits"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant VOutMinSet_flow(
    final k=minVOutSet_flow)
    "Outdoor volumetric airflow rate setpoint, 15cfm/occupant and 100 occupants"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp VOut_flow(
    final duration=1800,
    final offset=VOutMin_flow,
    final height=incVOutSet_flow)
    "Measured outdoor airflow rate"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Economizers.Subsequences.Limits.Common damLim
    "Multi zone VAV AHU minimum outdoor air control - damper position limits"

protected
  parameter Real minVOutSet_flow(
    final unit="m3/s",
    final quantity="VolumeFlowRate")=0.71
    "Example volumetric airflow setpoint, 15cfm/occupant, 100 occupants";
  parameter Real VOutMin_flow(
    final unit="m3/s",
    final quantity="VolumeFlowRate")=0.61
    "Minimal measured volumetric airflow";
  parameter Real incVOutSet_flow(
    final unit="m3/s",
    final quantity="VolumeFlowRate")=(minVOutSet_flow-VOutMin_flow)*2
    "Maximum volumetric airflow increase during the example simulation";

  Buildings.Controls.OBC.CDL.Logical.Sources.Constant fanStatus(k=true) "Fan is on"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant operationMode(
    final k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied)
    "Operation mode is Occupied"

equation
  connect(VOut_flow.y, damLim.VOut_flow_normalized)
  connect(VOutMinSet_flow.y, damLim.VOutMinSet_flow_normalized)
  connect(fanStatus.y, damLim.u1SupFan)
  connect(operationMode.y, damLim.uOpeMod)
end Common_VOut_flow;