Sequence for controlling relief fan group. Sequence for controlling group of relief fans and their dampers for AHUs using actuated
relief dampers with relief fan(s). It is developed based on Section 5.16.9 of ASHRAE
Guideline 36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints;
block ReliefFanGroup
  "Sequence for controlling relief fan group"

  parameter Integer nSupFan = 2
    "Total number of AHU supply fans that are serving the same common space"
  parameter Integer nRelFan = 4
    "Total number of relief fans that are serving the same common space"
  parameter Real relFanSpe_min(
    final min=0,
    final max=1)= 0.1
    "Relief fan minimum speed"
  parameter Integer staVec[nRelFan] = {2,3,1,4}
    "Vector of the order for staging up relief fan, i.e. the 1st element means the 1st relief fan and its value showing its sequence when staging up";
  parameter Integer relFanMat[nRelFan, nSupFan] = {{1,0},{1,0},{0,1},{0,1}}
    "Relief fan matrix with relief fan as row index and AHU supply fan as column index. It flags which relief fan is associated with which supply fan";
  parameter Real dpBuiSet(
    final unit="Pa",
    final quantity="PressureDifference",
    final max=30) = 12
    "Building static pressure difference relative to ambient (positive to pressurize the building)"
  parameter Real k(
    final unit="1") = 1
    "Gain, normalized using dpBuiSet"
  parameter Real hys = 0.005
    "Hysteresis for checking the controller output value"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SupFan[nSupFan]
    "AHU supply fan proven on status"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpBui(
    final unit="Pa",
    displayUnit="Pa",
    final quantity="PressureDifference")
    "Building static pressure difference, relative to ambient (positive if pressurized)"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uRelFanAla[nRelFan]
    "Relief fan current alarm index"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1RelFan[nRelFan]
    "Relief fan proven on status"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yDpBui(
    final unit="Pa",
    displayUnit="Pa",
    final quantity="PressureDifference")
    "Building static pressure difference, relative to ambient (positive if pressurized)"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRelFan[nRelFan](
    final unit=fill("1", nRelFan),
    final max=fill(1, nRelFan)) "Relief fan commanded speed"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yDam[nRelFan](
    final unit=fill("1",nRelFan),
    final min=fill(0,nRelFan),
    final max=fill(1,nRelFan)) "Damper commanded position"

  Buildings.Controls.OBC.CDL.Reals.MatrixGain enaRel(
    final K=relFanMat)
    "Vector of relief fans with the enabled one denoted by 1"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nSupFan]
    "Convert boolean to real"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai[nRelFan](
    final k=staVec)
    "Vector of enabling fan, along with its staging order"
  Buildings.Controls.OBC.CDL.Reals.MovingAverage movMea(
    final delta=300)
    "Average building static pressure measurement"
  Buildings.Controls.OBC.CDL.Reals.Divide div1
    "Normalized the control error"
  Buildings.Controls.OBC.CDL.Reals.PID conP(
    final controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.P,
    final k=k,
    final reverseActing=false)
    "Building static pressure controller"
  Buildings.Controls.OBC.CDL.Logical.MultiOr enaRelGro(
    final nin=nSupFan)
    "Relief group enabling status"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea1
    "Convert boolean to real"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro
    "Set controller output to zero when the relief system is disabled"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr(
    final t=0.05,
    final h=hys)
    "Check if the controller output is greater than threshold"
  Buildings.Controls.OBC.CDL.Logical.And and2
    "Check if the controller output is greater than threshold and the relief system has been enabled"
  Buildings.Controls.OBC.CDL.Logical.Latch lat "Enable damper"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lesThr(
    final t=0.005,
    final h=hys)
    "Check if the controller output is near zero"
  Buildings.Controls.OBC.CDL.Logical.Timer tim(
    final t=300)
    "Check if the controller output has been near zero for threshold time"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep(
    final nout=nRelFan)
    "Boolean replicator"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr1[nRelFan](
    final t=fill(0.5, nRelFan))
    "Check if a relief fan should be enabled"
  Buildings.Controls.OBC.CDL.Logical.And enaDam[nRelFan]
    "Enable damper"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr2(
    final t=relFanSpe_min + 0.15,
    final h=hys)
    "Check if the controller output is greater than minimum speed plus threshold"
  Buildings.Controls.OBC.CDL.Logical.Timer upTim(
    final t=420)
    "Check if the controller output has been greater than threshold for sufficient long time"
  Buildings.Controls.OBC.CDL.Logical.Pre pre(
    final pre_u_start=true)
    "Break algebraic loop"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea2[nRelFan]
    "Convert boolean to real"
  Buildings.Controls.OBC.CDL.Reals.Subtract sub2[nRelFan]
    "Identify relief fans that have been enabled but not yet operating"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro1[nRelFan]
    "List of standby fans, along with their staging order"
  Buildings.Controls.OBC.CDL.Reals.MultiMin mulMin(nin=nRelFan)
    "Identify current order of staging"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep(
    final nout=nRelFan)
    "Replicate real number"
  Buildings.Controls.OBC.CDL.Reals.Subtract sub1[nRelFan]
    "Identify next operating fan"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lesThr1[nRelFan](
    final t=fill(0.5, nRelFan))
    "Check if the input is less than threshold"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar[nRelFan](
    final p=fill(nRelFan + 1, nRelFan))
    "Add value to the input"
  Buildings.Controls.OBC.CDL.Reals.Switch swi[nRelFan]
    "Switch input values"
  Buildings.Controls.OBC.CDL.Reals.Abs abs1[nRelFan]
    "Find absolute value"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lesThr2[nRelFan](
    final t=fill(0.5, nRelFan))
    "Identify next operating fan"
  Buildings.Controls.OBC.CDL.Logical.Or or2[nRelFan]
    "Targeted vector of operating relief fan after one new fan being turned on"
  Buildings.Controls.OBC.CDL.Logical.Latch lat2
    "Stage up next relief fan"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lesThr3(
    final t=relFanSpe_min,
    final h=hys)
    "Check if the controller output is less than minimum speed"
  Buildings.Controls.OBC.CDL.Logical.Timer dowTim(
    final t=300)
    "Check if the controller output has been less than threshold for sufficient long time"
  Buildings.Controls.OBC.CDL.Logical.Pre pre1(
    final pre_u_start=true)
    "Break algebraic loop"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro2[nRelFan]
    "List of operating fans, along with their staging order"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar1[nRelFan](
    final p=fill(nRelFan + 1, nRelFan))
    "Add value to the input"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lesThr4[nRelFan](
    final t=fill(0.5, nRelFan))
    "Check if the input is less than threshold"
  Buildings.Controls.OBC.CDL.Reals.Switch swi1[nRelFan]
    "Switch input values"
  Buildings.Controls.OBC.CDL.Reals.MultiMin mulMin1(
    final nin=nRelFan) "Minimum staging order of the running relief fans"
  Buildings.Controls.OBC.CDL.Reals.Subtract sub3[nRelFan]
    "Identify next operating fan"
  Buildings.Controls.OBC.CDL.Reals.Abs abs2[nRelFan]
    "Find absolute value"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lesThr5[nRelFan](
    final t=fill(0.5, nRelFan))
    "Identify next fan to be off"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep1(
    final nout=nRelFan)
    "Replicate real number"
  Buildings.Controls.OBC.CDL.Logical.Xor xor[nRelFan]
    "Vector of relief fan after one fan being turned off"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nRelFan]
    "Convert boolean to integer"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1[nRelFan]
    "Convert boolean to integer"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt2[nRelFan]
    "Convert boolean to integer"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu[nRelFan]
    "Check if newly started fan has become proven on"
  Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd(
    final nin=nRelFan)
    "Check if newly started fan has become proven on"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu1[nRelFan]
    "Check if newly turned off fan has become off"
  Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd2(
    final nin=nRelFan)
    "Check if newly turned off fan has become off"
  Buildings.Controls.OBC.CDL.Logical.Latch lat1
    "Stage down lag fan"
  Buildings.Controls.OBC.CDL.Logical.Switch logSwi[nRelFan]
    "Vector of relief fan status after staging up"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep1(
    final nout=nRelFan)
    "Replicate boolean input"
  Buildings.Controls.OBC.CDL.Logical.Switch logSwi1[nRelFan]
    "Vector of relief fan status after staging down"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep2(
    final nout=nRelFan)
    "Replicate boolean input"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea3[nRelFan]
    "Convert boolean to real"
  Buildings.Controls.OBC.CDL.Reals.Limiter lim(
    final uMax=1,
    final uMin=relFanSpe_min)
    "Limit the controller output"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep2(
    final nout=nRelFan)
    "Replicate real input"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro3[nRelFan]
    "Relief fan speed"
  Buildings.Controls.OBC.CDL.Logical.Switch logSwi2[nRelFan]
    "Vector of relief fan status after staging up"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpBuiSetPoi(
    final k=dpBuiSet)
    "Building pressure setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant conOne(
    final k=1)
    "Constant one"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(
    final k=0)
    "Zero fan speed when it is in stage 0"
  Buildings.Controls.OBC.CDL.Reals.Switch swi2
    "Switch input values"
  Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr(nin=nRelFan)
    "Check if there is any relief fan enabled, but may not be running"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea4[nRelFan]
    "Convert boolean to real"
  Buildings.Controls.OBC.CDL.Logical.Not not1
    "Logical not"
  Buildings.Controls.OBC.CDL.Logical.And and1
    "Start timer, and reset to zero if the threshold time has passed"
  Buildings.Controls.OBC.CDL.Logical.And and3
    "Start timer, and reset to zero if the threshold time has passed"
  Buildings.Controls.OBC.CDL.Logical.Not not2 "Logical not"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu2[nRelFan]
    "Check if the relief fan is in level 2 alarm"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[nRelFan](
    final k=fill(2, nRelFan))
    "Constant"
  Buildings.Controls.OBC.CDL.Logical.Not not3[nRelFan] "Logical not"
  Buildings.Controls.OBC.CDL.Logical.And and4[nRelFan]
    "Check if the relief fan is in level 2 alarm and it is proven off"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea5[nRelFan](
    final realTrue=fill(0, nRelFan),
    final realFalse=fill(1, nRelFan))
    "Convert boolean to real"
  Buildings.Controls.OBC.CDL.Reals.Multiply mul[nRelFan]
    "Product of inputs"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr3[nRelFan](
    final t=fill(0.5, nRelFan))
    "Check if the relief fan is enabled"
  Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd1(
    final nin=nRelFan) "Check if all the fans are proven off"
  Buildings.Controls.OBC.CDL.Reals.Switch swi3[nRelFan]
    "Switch input values"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep4(
    final nout=nRelFan)
    "Replicate boolean input"
  Buildings.Controls.OBC.CDL.Logical.Switch logSwi3[nRelFan]
    "Vector of relief fan status after staging down"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel[nRelFan](
    final delayTime=fill(2, nRelFan))
    "Delay true input"
  Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr1(
    final nin=nRelFan)
    "Check if there is any fan is proven on"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator booRep5(
    final nout=nRelFan)
    "Replicate boolean input"
  Buildings.Controls.OBC.CDL.Logical.Not not5[nRelFan] "Logical not"
  Buildings.Controls.OBC.CDL.Logical.Not not6[nRelFan] "Logical not"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel1[nRelFan](
    final delayTime=fill(2, nRelFan))
    "Delay true input"

equation
  connect(u1SupFan, booToRea.u)
  connect(enaRel.u, booToRea.y)
  connect(enaRel.y, gai.u)
  connect(dpBui, movMea.u)
  connect(conOne.y, conP.u_s)
  connect(movMea.y, div1.u1)
  connect(dpBuiSetPoi.y, div1.u2)
  connect(div1.y, conP.u_m)
  connect(u1SupFan, enaRelGro.u)
  connect(booToRea1.y, pro.u1)
  connect(enaRelGro.y, booToRea1.u)
  connect(conP.y, greThr.u)
  connect(enaRelGro.y, and2.u2)
  connect(greThr.y, and2.u1)
  connect(and2.y, lat.u)
  connect(conP.y, lesThr.u)
  connect(lesThr.y, tim.u)
  connect(tim.passed, lat.clr)
  connect(lat.y, booRep.u)
  connect(gai.y, greThr1.u)
  connect(greThr1.y, enaDam.u1)
  connect(booRep.y, enaDam.u2)
  connect(u1RelFan, booToRea2.u)
  connect(enaRel.y, sub2.u1)
  connect(booToRea2.y, sub2.u2)
  connect(gai.y, pro1.u1)
  connect(sub2.y, pro1.u2)
  connect(mulMin.y, reaRep.u)
  connect(lesThr1.y, swi.u2)
  connect(pro1.y, swi.u3)
  connect(pro1.y, addPar.u)
  connect(addPar.y, swi.u1)
  connect(gai.y, sub1.u1)
  connect(reaRep.y, sub1.u2)
  connect(sub1.y, abs1.u)
  connect(abs1.y, lesThr2.u)
  connect(lesThr2.y, or2.u1)
  connect(booToRea2.y, pro2.u2)
  connect(gai.y, pro2.u1)
  connect(pro2.y, addPar1.u)
  connect(pro2.y, lesThr4.u)
  connect(lesThr4.y, swi1.u2)
  connect(addPar1.y, swi1.u1)
  connect(pro2.y, swi1.u3)
  connect(swi1.y, mulMin1.u)
  connect(mulMin1.y, reaRep1.u)
  connect(reaRep1.y, sub3.u2)
  connect(gai.y, sub3.u1)
  connect(sub3.y, abs2.u)
  connect(abs2.y, lesThr5.u)
  connect(lesThr5.y, xor.u1)
  connect(booToInt.y, intEqu.u1)
  connect(booToInt1.y, intEqu.u2)
  connect(intEqu.y, mulAnd.u)
  connect(booToInt1.y, intEqu1.u1)
  connect(booToInt2.y, intEqu1.u2)
  connect(intEqu1.y, mulAnd2.u)
  connect(lat2.y, booRep1.u)
  connect(lat1.y, booRep2.u)
  connect(booRep2.y, logSwi1.u2)
  connect(mulAnd2.y, lat1.clr)
  connect(conP.y, lesThr3.u)
  connect(xor.y, logSwi1.u1)
  connect(conP.y, greThr2.u)
  connect(booRep1.y, logSwi.u2)
  connect(or2.y, logSwi.u1)
  connect(u1RelFan, xor.u2)
  connect(u1RelFan, logSwi1.u3)
  connect(u1RelFan, booToInt1.u)
  connect(u1RelFan, or2.u2)
  connect(logSwi.y, booToRea3.u)
  connect(conP.y, lim.u)
  connect(lim.y, pro.u2)
  connect(booToRea3.y, pro3.u2)
  connect(pro3.y, yRelFan)
  connect(reaRep2.y, pro3.u1)
  connect(con.y, swi2.u3)
  connect(mulOr.y, swi2.u2)
  connect(movMea.y, yDpBui)
  connect(logSwi2.y, booToRea4.u)
  connect(not1.y, pre.u)
  connect(and1.y, upTim.u)
  connect(greThr2.y, and1.u1)
  connect(not2.y, pre1.u)
  connect(lesThr3.y, and3.u1)
  connect(and3.y, dowTim.u)
  connect(uRelFanAla, intEqu2.u1)
  connect(conInt.y, intEqu2.u2)
  connect(u1RelFan, not3.u)
  connect(intEqu2.y, and4.u1)
  connect(not3.y, and4.u2)
  connect(and4.y, booToRea5.u)
  connect(booToRea4.y, mul.u1)
  connect(booToRea5.y, mul.u2)
  connect(mul.y, yDam)
  connect(enaDam.y, logSwi2.u3)
  connect(logSwi.y, logSwi2.u1)
  connect(upTim.passed, not1.u)
  connect(upTim.passed, lat2.u)
  connect(dowTim.passed, not2.u)
  connect(dowTim.passed, lat1.u)
  connect(enaRel.y, greThr3.u)
  connect(greThr3.y, mulOr.u)
  connect(pro.y, swi2.u1)
  connect(swi2.y, reaRep2.u)
  connect(pro1.y, lesThr1.u)
  connect(not3.y, mulAnd1.u)
  connect(mulAnd1.y, booRep4.u)
  connect(booRep4.y, swi3.u2)
  connect(pro1.y, swi3.u1)
  connect(swi.y, swi3.u3)
  connect(swi3.y, mulMin.u)
  connect(pre1.y, and3.u2)
  connect(u1RelFan, logSwi3.u1)
  connect(booRep4.y, logSwi3.u2)
  connect(logSwi1.y, logSwi3.u3)
  connect(logSwi3.y, logSwi.u3)
  connect(pre.y, and1.u2)
  connect(truDel.y, booToInt.u)
  connect(or2.y, truDel.u)
  connect(mulAnd.y, lat2.clr)
  connect(logSwi.y, mulOr1.u)
  connect(mulOr1.y, booRep5.u)
  connect(booRep5.y, logSwi2.u2)
  connect(not6.y, booToInt2.u)
  connect(truDel1.y, not6.u)
  connect(not5.y, truDel1.u)
  connect(xor.y, not5.u)
end ReliefFanGroup;


Return fan control for AHUs using return fan with airflow tracking. Sequence for controlling return fan yRetFan for AHUs using return fan
with airflow tracking.
It is implemented according to Section 5.16.11 of ASHRAE Guideline G36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints;
block ReturnFanAirflowTracking
  "Return fan control for AHUs using return fan with airflow tracking"
  parameter Real difFloSet(
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    "Airflow differential between supply air and return air fans required to maintain building pressure at desired pressure"
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController conTyp=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller"
  parameter Real k(final unit="1") = 1
    "Gain, normalized using dpBuiSet"
  parameter Real Ti(
    final unit="s",
    final quantity="Time")=0.5
    "Time constant of integrator block"
  parameter Real Td(
    final unit="s",
    final quantity="Time")=0.1
    "Time constant of derivative block"
  parameter Real maxSpe=1
    "Upper limit of output"
  parameter Real minSpe=0
    "Lower limit of output"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput VAirSup_flow(
    final unit="m3/s",
    final min=0,
    final quantity="VolumeFlowRate") "Measured AHU supply airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VAirRet_flow(
    final unit="m3/s",
    final min=0,
    final quantity="VolumeFlowRate") "Measured AHU return airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SupFan
    "Supply fan status"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetFan(
    final unit="1",
    final min=0,
    final max=1) "Return fan commanded speed"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1RetFan
    "Return fan commanded on"
  Buildings.Controls.OBC.CDL.Reals.PID conP(
    final controllerType=conTyp,
    final k=k,
    final Ti=Ti,
    final Td=Td,
    final yMax=maxSpe,
    final yMin=minSpe)
    "Building static pressure controller"

protected
  Buildings.Controls.OBC.CDL.Reals.Switch swi
    "Check if relief damper should be enabled"
  Buildings.Controls.OBC.CDL.Reals.Subtract conErr(
    u1(final unit="m3/s", displayUnit="m3/s"),
    u2(final unit="m3/s", displayUnit="m3/s"),
    y(final unit="m3/s", displayUnit="m3/s"))
    "Control error"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zerSpe(
    final k=0) "Disable return fan"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant difFlo(
    final k=difFloSet) "Return airflow less than supply airflow"

equation
  connect(u1SupFan, swi.u2)
  connect(zerSpe.y, swi.u3)
  connect(swi.y,yRetFan)
  connect(VAirSup_flow, conErr.u1)
  connect(difFlo.y, conErr.u2)
  connect(conErr.y, conP.u_s)
  connect(VAirRet_flow, conP.u_m)
  connect(conP.y, swi.u1)
  connect(u1SupFan, y1RetFan)
end ReturnFanAirflowTracking;


Return fan control with direct building pressure control. Setpoint for return fan discharge pressure and relief air damper
for a multi zone VAV AHU according to Section 5.16.10 of ASHRAE Guideline G36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints;
block ReturnFanDirectPressure
  "Return fan control with direct building pressure control"

  parameter Real dpBuiSet(
    final unit="Pa",
    final quantity="PressureDifference",
    final max=30) = 12
    "Building static pressure difference relative to ambient (positive to pressurize the building)"
  parameter Real p_rel_RetFan_min(
    final unit="Pa",
    final quantity="PressureDifference",
    final min=0,
    final max=1000) = 2.4
    "Return fan discharge static pressure difference minimum setpoint,no less than 2.4 Pa"
  parameter Real p_rel_RetFan_max(
    final unit="Pa",
    final quantity="PressureDifference",
    final min=0,
    final max=1000) = 40
    "Return fan discharge static pressure maximum setpoint"
  parameter Real disSpe_min(
    final unit="1",
    final min=0,
    final max=1)
    "Return fan speed when providing the minimum return fan discharge static pressure difference";
  parameter Real disSpe_max(
    final unit="1",
    final min=0,
    final max=1)
    "Return fan speed when providing the maximum return fan discharge static pressure difference";
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController conTyp=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller"
  parameter Real k(final unit="1") = 1
    "Gain, normalized using dpBuiSet"
  parameter Real Ti(
    final unit="s",
    final quantity="Time")=0.5
    "Time constant of integrator block"
  parameter Real Td(
    final unit="s",
    final quantity="Time")=0.1
    "Time constant of derivative block"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpBui(
    final unit="Pa",
    displayUnit="Pa")
    "Building static pressure difference, relative to ambient (positive if pressurized)"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1MinOutAirDam
    "Minimum outdoor air damper status, true when it is open"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SupFan
    "Supply fan status"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yDpBui(
    final unit="Pa",
    displayUnit="Pa")
    "Averaged building static pressure"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRelDam(
    final unit="1",
    final min=0,
    final max=1)
    "Relief damper commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dpDisSet(
     final unit="Pa",
     displayUnit="Pa",
     final min=0) "Return fan discharge static pressure setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yRetFan(
    final unit="1",
    final min=0,
    final max=1)
    "Return fan commanded speed"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1RetFan
    "Return fan commanded on"

  Buildings.Controls.OBC.CDL.Reals.MovingAverage movMea(
    final delta=300)
    "Average building static pressure measurement"
  Buildings.Controls.OBC.CDL.Reals.PID conP(
    final controllerType=conTyp,
    final k=k,
    final Ti=Ti,
    final Td=Td)
    "Building static pressure controller"
  Buildings.Controls.OBC.CDL.Reals.Line linExhAirDam
    "Exhaust air damper position"
  Buildings.Controls.OBC.CDL.Reals.Line linRetFanStaPre
    "Return fan static pressure setpoint"
  Buildings.Controls.OBC.CDL.Reals.Switch swi1
    "Relief air damper position"
  Buildings.Controls.OBC.CDL.Reals.Switch swi
    "Return fan discharge static pressure setpoint"
  Buildings.Controls.OBC.CDL.Reals.Divide div "Normalized the control error"
  Buildings.Controls.OBC.CDL.Reals.Line linRetFanSpe "Return fan speed"
  Buildings.Controls.OBC.CDL.Reals.Switch swi2
    "Return fan speed setpoint"

protected
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpBuiSetPoi(
    final k=dpBuiSet) "Building pressure setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant retFanDisPreMin(
    final k=p_rel_RetFan_min) "Return fan discharge static pressure minimum setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant retFanDisPreMax(
    final k=p_rel_RetFan_max) "Return fan discharge static pressure maximum setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(final k=0)
    "Zero fan control signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1(final k=0)
    "Zero constant"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(final k=0.5)
    "Constant 0.5"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(final k=1)
    "Constant one"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant conOne(final k=1)
    "Constant one"
  Buildings.Controls.OBC.CDL.Logical.And enaDam
    "Check if the relief damper should be enabled"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant retFanSpeMin(
    final k=disSpe_min)
    "Return fan speed when discharge static pressure minimum setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant retFanSpeMax(
    final k=disSpe_max)
    "Return fan speed when discharge static pressure maximum setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer2(
    final k=0)
    "Zero fan control signal"

equation
  connect(movMea.u, dpBui)
  connect(swi.u2, u1SupFan)
  connect(swi.u3, zer.y)
  connect(zer1.y, linExhAirDam.x1)
  connect(zer1.y, linExhAirDam.f1)
  connect(con.y, linExhAirDam.x2)
  connect(one.y, linExhAirDam.f2)
  connect(con.y, linRetFanStaPre.x1)
  connect(one.y, linRetFanStaPre.x2)
  connect(retFanDisPreMin.y, linRetFanStaPre.f1)
  connect(retFanDisPreMax.y, linRetFanStaPre.f2)
  connect(linRetFanStaPre.y, swi.u1)
  connect(linExhAirDam.y, swi1.u1)
  connect(swi1.y,yRelDam)
  connect(zer1.y, swi1.u3)
  connect(swi.y, dpDisSet)
  connect(conP.y, linExhAirDam.u)
  connect(conP.y, linRetFanStaPre.u)
  connect(dpBuiSetPoi.y, div.u2)
  connect(movMea.y, div.u1)
  connect(conOne.y, conP.u_s)
  connect(div.y, conP.u_m)
  connect(movMea.y, yDpBui)
  connect(u1MinOutAirDam, enaDam.u1)
  connect(u1SupFan, enaDam.u2)
  connect(enaDam.y, swi1.u2)
  connect(linRetFanStaPre.y, linRetFanSpe.u)
  connect(retFanDisPreMin.y, linRetFanSpe.x1)
  connect(retFanSpeMin.y, linRetFanSpe.f1)
  connect(retFanDisPreMax.y, linRetFanSpe.x2)
  connect(retFanSpeMax.y, linRetFanSpe.f2)
  connect(linRetFanSpe.y, swi2.u1)
  connect(zer2.y, swi2.u3)
  connect(u1SupFan, swi2.u2)
  connect(swi2.y, yRetFan)
  connect(u1SupFan, y1RetFan)
end ReturnFanDirectPressure;


Block to control multi zone VAV AHU supply fan. Supply fan control for a multi zone VAV AHU according to Section 5.16.1 of
ASHRAE Guideline G36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints;
block SupplyFan  "Block to control multi zone VAV AHU supply fan"

  parameter Boolean have_perZonRehBox = false
    "Check if there is any VAV-reheat boxes on perimeter zones"
  parameter Real iniSet(
    final unit="Pa",
    final quantity="PressureDifference") = 120
    "Initial setpoint"
  parameter Real minSet(
    final unit="Pa",
    final quantity="PressureDifference") = 25
    "Minimum setpoint"
  parameter Real maxSet(
    final unit="Pa",
    final quantity="PressureDifference")
    "Duct design maximum static pressure. It is the Max_DSP shown in Section 3.2.1.1 of Guideline 36"
  parameter Real delTim(
    final unit="s",
    final quantity="Time")= 600
   "Delay time after which trim and respond is activated"
  parameter Real samplePeriod(
    final unit="s",
    final quantity="Time") = 120  "Sample period"
  parameter Integer numIgnReq = 2
    "Number of ignored requests"
  parameter Real triAmo(
    final unit="Pa",
    final quantity="PressureDifference") = -12.0
    "Trim amount"
  parameter Real resAmo(
    final unit="Pa",
    final quantity="PressureDifference") = 15
    "Respond amount (must be opposite in to triAmo)"
  parameter Real maxRes(
    final unit="Pa",
    final quantity="PressureDifference") = 32
    "Maximum response per time interval (same sign as resAmo)"
  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.1
    "Gain of controller, normalized using maxSet"
  parameter Real Ti(
    final unit="s",
    final quantity="Time",
    min=0)=60
    "Time constant of integrator block"
  parameter Real Td(
    final unit="s",
    final quantity="Time",
    final min=0) = 0.1
    "Time constant of derivative block"
  parameter Real maxSpe(min=0.1, max=1, unit="1") = 1
    "Maximum allowed fan speed"
  parameter Real minSpe(min=0.1, max=1, unit="1") = 0.1
    "Lowest allowed fan speed if fan is on"
  parameter Real iniSpe(min=minSpe, max=1, unit="1") = 0.1
    "Initial speed when fan is enabled. It has to be greater than the lowest allowed speed"

  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod
   "System operation mode"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpDuc(
    final unit="Pa",
    final quantity="PressureDifference") "Measured duct static pressure"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uZonPreResReq
    "Zone static pressure reset requests"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1SupFan
    "Supply fan command on"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput ySupFan(
    min=0,
    max=1,
    final unit="1")
    "Supply fan commanded speed"

  Buildings.Controls.OBC.ASHRAE.G36.Generic.TrimAndRespond staPreSetRes(
    final iniSet=iniSet,
    final minSet=minSet,
    final maxSet=maxSet,
    final delTim=delTim,
    final samplePeriod=samplePeriod,
    final numIgnReq=numIgnReq,
    final triAmo=triAmo,
    final resAmo=resAmo,
    final maxRes=maxRes)
    "Static pressure setpoint reset using trim and respond logic"
  Buildings.Controls.OBC.CDL.Reals.PIDWithReset conSpe(
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti,
    final Td=Td,
    final yMax=maxSpe,
    final yMin=minSpe,
    final y_reset=iniSpe) "Supply fan speed control"

protected
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zerSpe(k=0)
    "Zero fan speed when it becomes OFF"
  Buildings.Controls.OBC.CDL.Reals.Switch swi
    "If fan is OFF, fan speed outputs to zero"
  Buildings.Controls.OBC.CDL.Logical.Or or1
    "Check whether supply fan should be ON"
  Buildings.Controls.OBC.CDL.Logical.Or or2 if have_perZonRehBox
    "Setback or warmup mode"
  Buildings.Controls.OBC.CDL.Logical.Or or3
    "Cool-down or setup or occupied mode"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant con(
    k=false) if not have_perZonRehBox
    "Constant true"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt(
    k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.coolDown)
    "Cool down mode"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt4(
    k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.warmUp)
    "Warm-up mode"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt1(
    k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.setUp)
    "Set up mode"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt2(
    k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied)
    "Occupied mode"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt3(
    k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.setBack)
    "Set back mode"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu
    "Check if current operation mode is cool-down mode"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu1
    "Check if current operation mode is setup mode"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu2
    "Check if current operation mode is occupied mode"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu3
    "Check if current operation mode is setback mode"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu4
    "Check if current operation mode is warmup mode"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant gaiNor(
    final k=maxSet)
    "Gain for normalization of controller input"
  Buildings.Controls.OBC.CDL.Reals.Divide norPSet
    "Normalization for pressure set point"
  Buildings.Controls.OBC.CDL.Reals.Divide norPMea
    "Normalization of pressure measurement"
  Buildings.Controls.OBC.CDL.Discrete.FirstOrderHold firOrdHol(
    final samplePeriod=samplePeriod)
    "Extrapolation through the values of the last two sampled input signals"
  Buildings.Controls.OBC.CDL.Logical.Or or4
    "Cool-down or setup or occupied mode"

equation
  connect(or2.y, or1.u2)
  connect(or1.y, y1SupFan)
  connect(or1.y, staPreSetRes.uDevSta)
  connect(or1.y, swi.u2)
  connect(conSpe.y, swi.u1)
  connect(zerSpe.y, swi.u3)
  connect(swi.y, ySupFan)
  connect(uZonPreResReq, staPreSetRes.numOfReq)
  connect(con.y, or1.u2)
  connect(intEqu.y, or3.u1)
  connect(intEqu1.y, or3.u2)
  connect(conInt.y, intEqu.u2)
  connect(conInt1.y, intEqu1.u2)
  connect(conInt2.y, intEqu2.u2)
  connect(conInt3.y, intEqu3.u2)
  connect(conInt4.y, intEqu4.u2)
  connect(uOpeMod, intEqu.u1)
  connect(uOpeMod, intEqu1.u1)
  connect(uOpeMod, intEqu2.u1)
  connect(uOpeMod, intEqu3.u1)
  connect(uOpeMod, intEqu4.u1)
  connect(intEqu3.y, or2.u1)
  connect(intEqu4.y, or2.u2)
  connect(norPSet.y, conSpe.u_s)
  connect(norPMea.y, conSpe.u_m)
  connect(staPreSetRes.y, firOrdHol.u)
  connect(conSpe.trigger, or1.y)
  connect(gaiNor.y, norPSet.u2)
  connect(dpDuc, norPMea.u1)
  connect(gaiNor.y, norPMea.u2)
  connect(firOrdHol.y, norPSet.u1)
  connect(intEqu2.y, or4.u1)
  connect(or4.y, or1.u1)
  connect(or3.y, or4.u2)
end SupplyFan;


Multizone VAV AHU supply air temperature control loop and coil valves position. Block that outputs the supply temperature control loop signal,
and the coil valve postions for VAV system with multiple zones,
implemented according to Section 5.16.2.3 of the ASHRAE Guideline G36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints;
block SupplySignals
  "Multizone VAV AHU supply air temperature control loop and coil valves position"

  parameter Boolean have_heaCoi=true
    "True: the AHU has heating coil. It could be the hot water coil, or the electric heating coil"
  parameter Boolean have_cooCoi=true
    "True: the AHU has cooling coil. It could be the chilled water coil, or the direct expansion coil"
  parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType=
      Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller for supply air temperature signal"
  parameter Real kTSup(final unit="1/K")=0.05
    "Gain of controller for supply air temperature signal"
  parameter Real TiTSup(
    final unit="s",
    final quantity="Time")=600
    "Time constant of integrator block for supply temperature control signal"
  parameter Real TdTSup(
    final unit="s",
    final quantity="Time")=0.1
    "Time constant of derivative block for supply temperature control signal"
  parameter Real uHea_max(
    final min=-0.9,
    final unit="1")=-0.25
    "Upper limit of controller signal when heating coil is off. Require -1 < uHea_max < uCoo_min < 1."
  parameter Real uCoo_min(
    final max=0.9,
    final unit="1")=0.25
    "Lower limit of controller signal when cooling coil is off. Require -1 < uHea_max < uCoo_min < 1."

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TAirSup(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "Measured supply air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TAirSupSet(
    final unit="K",
    final displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "Supply air temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SupFan
    "Supply fan status"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yHeaCoi(
    final min=0,
    final max=1,
    final unit="1") if have_heaCoi "Heating coil commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yCooCoi(
    final min=0,
    final max=1,
    final unit="1") if have_cooCoi
    "Cooling coil commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput uTSup(
    final max=1,
    final unit="1",
    final min=-1)
    "Supply temperature control signal"

  Buildings.Controls.OBC.CDL.Reals.PIDWithReset conTSup(
    final controllerType=controllerType,
    final k=kTSup,
    final Ti=TiTSup,
    final Td=TdTSup,
    final yMax=1,
    final yMin=-1,
    final reverseActing=false,
    final y_reset=0)
    "Controller for supply air temperature control signal (to be used by heating coil, cooling coil and economizer)"

protected
  Buildings.Controls.OBC.CDL.Reals.Switch swi
    "Switch to select supply temperature control signal based on status of supply fan"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant uHeaMaxCon(
    final k=uHea_max) if have_heaCoi
    "Constant signal to map control action"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant negOne(final k=-1)
    if have_heaCoi
    "Negative unity signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant uCooMinCon(
    final k=uCoo_min) if have_cooCoi
    "Constant signal to map control action"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(final k=0)
    "Zero control signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(final k=1)
    "Unity signal"
  Buildings.Controls.OBC.CDL.Reals.Line conSigCoo(
    final limitBelow=true,
    final limitAbove=false) if have_cooCoi
    "Cooling control signal"
  Buildings.Controls.OBC.CDL.Reals.Line conSigHea(
    final limitBelow=false,
    final limitAbove=true) if have_heaCoi
    "Heating control signal"

equation
  connect(zer.y,swi. u3)
  connect(TAirSup, conTSup.u_m)
  connect(negOne.y,conSigHea. x1)
  connect(one.y,conSigHea. f1)
  connect(swi.y,conSigHea. u)
  connect(swi.y,conSigCoo. u)
  connect(uHeaMaxCon.y,conSigHea. x2)
  connect(zer.y,conSigHea. f2)
  connect(uCooMinCon.y,conSigCoo. x1)
  connect(zer.y,conSigCoo. f1)
  connect(one.y,conSigCoo. x2)
  connect(one.y,conSigCoo. f2)
  connect(conSigHea.y, yHeaCoi)
  connect(conSigCoo.y, yCooCoi)
  connect(swi.y,uTSup)
  connect(TAirSupSet, conTSup.u_s)
  connect(u1SupFan, swi.u2)
  connect(conTSup.y, swi.u1)
  connect(u1SupFan, conTSup.trigger)
end SupplySignals;


Supply air temperature setpoint for multi zone system. Block that outputs the supply air temperature setpoint and the coil valve control
inputs for VAV system with multiple zones, implemented according to Section 5.16.2 of
the ASHRAE Guideline G36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints;
block SupplyTemperature
  "Supply air temperature setpoint for multi zone system"

  parameter Real TSupCoo_min(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=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(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=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(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=289.15
    "Lower value of the outdoor air temperature reset range. Typically value is 16 degC (60 degF)"
  parameter Real TOut_max(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=294.15
    "Higher value of the outdoor air temperature reset range. Typically value is 21 degC (70 degF)"
  parameter Real TSupWarUpSetBac(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=308.15
    "Supply temperature in warm up and set back mode"
  parameter Real delTim(
    final unit="s",
    final quantity="Time") = 600
    "Delay timer"
  parameter Real samplePeriod(
    final unit="s",
    final quantity="Time",
    final min=1E-3) = 120
    "Sample period of component"
  parameter Integer numIgnReq = 2
    "Number of ignorable requests for TrimResponse logic"
  parameter Real triAmo(
    final unit="K",
    displayUnit="K",
    final quantity="TemperatureDifference") = 0.1
    "Trim amount"
  parameter Real resAmo(
    final unit="K",
    displayUnit="K",
    final quantity="TemperatureDifference") = -0.2
    "Response amount"
  parameter Real maxRes(
    final unit="K",
    displayUnit="K",
    final quantity="TemperatureDifference") = -0.6
    "Maximum response per time interval"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "Outdoor air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SupFan
    "Supply fan status"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod
    "System operation mode"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uZonTemResReq
    "Zone cooling supply air temperature reset request"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TAirSupSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")
    "Supply air temperature setpoint"

  Buildings.Controls.OBC.ASHRAE.G36.Generic.TrimAndRespond maxSupTemRes(
    final delTim=delTim,
    final iniSet=iniSet,
    final minSet=minSet,
    final maxSet=maxSet,
    final samplePeriod=samplePeriod,
    final numIgnReq=numIgnReq,
    final triAmo=triAmo,
    final resAmo=resAmo,
    final maxRes=maxRes) "Maximum cooling supply temperature reset"

protected
  parameter Real TDeaBan(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=273.15+26
    "Default supply temperature setpoint when the AHU is disabled";
  parameter Real iniSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=TSupCoo_max
    "Initial setpoint"
  parameter Real maxSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=TSupCoo_max
    "Maximum setpoint"
  parameter Real minSet(
    final unit="K",
    displayUnit="degC",
    final quantity="ThermodynamicTemperature")=TSupCoo_min
    "Minimum setpoint"

  Buildings.Controls.OBC.CDL.Reals.Line lin
    "Supply temperature distributes linearly between minimum and maximum supply
    air temperature, according to outdoor temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minOutTem(
    final k=TOut_min)
    "Lower value of the outdoor air temperature reset range"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant maxOutTem(
    final k=TOut_max)
    "Higher value of the outdoor air temperature reset range"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minSupTem(
    final k=TSupCoo_min)
    "Lowest cooling supply air temperature setpoint"
  Buildings.Controls.OBC.CDL.Logical.And and1
    "Check if it is in Warmup or Setback mode"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant supTemWarUpSetBac(
    final k=TSupWarUpSetBac)
    "Supply temperature setpoint under warm-up and setback mode"
  Buildings.Controls.OBC.CDL.Reals.Switch swi1
    "If operation mode is warm-up or setback modes, setpoint shall be 35 degC"
  Buildings.Controls.OBC.CDL.Reals.Switch swi2
    "If operation mode is setup or cool-down, setpoint shall be the lowest cooling supply setpoint"
  Buildings.Controls.OBC.CDL.Reals.Switch swi3
    "Check output regarding supply fan status"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant cooDowMod(
    final k=3) "Cooldown mode index"
  Buildings.Controls.OBC.CDL.Integers.LessThreshold intLesThr1(
    final t=6)
    "Check if operation mode index is less than 6 (freeze protection mode)"
  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold intGreThr1(
    final t=3)
    "Check if operation mode index is greater than 3 (setup mode)"
  Buildings.Controls.OBC.CDL.Integers.LessThreshold intLesThr2(
    final t=3)
    "Check if operation mode index is less than 3 (setup mode)"
  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold  intGreThr2(
    final t=0)
    "Check if operation mode index is greater than 0 (unoccupied mode)"
  Buildings.Controls.OBC.CDL.Logical.And and2
    "Check if it is in occupied or setup mode"
  Buildings.Controls.OBC.CDL.Reals.Switch swi4
    "If operation mode is occupied or setup ,mode, setpoint shall be reset"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu
    "Check if it is in cooldown mode"

  CDL.Reals.Sources.Constant TDea(final k=TDeaBan)
    "Deadband supply temperature setpoint"
equation
  connect(minOutTem.y, lin.x1)
  connect(TOut, lin.u)
  connect(maxOutTem.y, lin.x2)
  connect(minSupTem.y, lin.f2)
  connect(and1.y, swi1.u2)
  connect(supTemWarUpSetBac.y, swi1.u1)
  connect(minSupTem.y, swi2.u1)
  connect(swi2.y, swi1.u3)
  connect(u1SupFan, swi3.u2)
  connect(swi1.y, swi3.u1)
  connect(intLesThr1.y, and1.u1)
  connect(intGreThr1.y, and1.u2)
  connect(uOpeMod, intLesThr1.u)
  connect(uOpeMod, intGreThr1.u)
  connect(uZonTemResReq, maxSupTemRes.numOfReq)
  connect(u1SupFan, maxSupTemRes.uDevSta)
  connect(maxSupTemRes.y, lin.f1)
  connect(swi3.y, TAirSupSet)
  connect(cooDowMod.y, intEqu.u2)
  connect(uOpeMod, intEqu.u1)
  connect(intEqu.y, swi2.u2)
  connect(uOpeMod, intLesThr2.u)
  connect(uOpeMod, intGreThr2.u)
  connect(intLesThr2.y, and2.u1)
  connect(intGreThr2.y, and2.u2)
  connect(and2.y, swi4.u2)
  connect(lin.y, swi4.u1)
  connect(swi4.y, swi2.u3)

  connect(TDea.y, swi4.u3)
  connect(TDea.y, swi3.u3)
end SupplyTemperature;


within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints;
package OutdoorAirFlow "Package of sequences for calculating minimum outdoor airflow rate"
end OutdoorAirFlow;


Outdoor airflow related calculations at the AHU level. This sequence outputs AHU level uncorrected minimum outdoor airflow rate
VUncOutAir_flow and effective minimum outdoor airflow rate
VEffOutAir_flow when complying with ASHRAE Standard 62.1 ventilation requirements.
It is implemented according to Section 5.16.3.1 of ASHRAE
Guideline G36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.ASHRAE62_1;
block AHU "Outdoor airflow related calculations at the AHU level"

  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection minOADes
    "Type of outdoor air section"
  parameter Real VUncDesOutAir_flow(unit="m3/s")
    "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")
    "Design total outdoor airflow rate. It can be determined using the 62MZCalc spreadsheet from ASHRAE 62.1 User's Manual"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput VSumAdjPopBreZon_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    "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")
    "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")
    "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") "Maximum zone outdoor air fraction"
  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.RealOutput VUncOutAir_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate") "Uncorrected minimum outdoor airflow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VEffAirOut_flow_min(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    "Effective minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput effOutAir_normalized(
    final unit="1")
    "Effective minimum outdoor airflow setpoint, normalized by the design total outdoor airflow rate "
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput outAir_normalized(
    final unit="1")
    if (minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
     or minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.SingleDamper)
    "Normalized outdoor airflow rate"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant uncDesOutAir(
    final k=VUncDesOutAir_flow)
    "Uncorrected design outdoor airflow rate, including diversity where applicable"
  Buildings.Controls.OBC.CDL.Reals.Add add2
    "Sum of the breathing zone outdoor airflow"
  Buildings.Controls.OBC.CDL.Reals.Min min1
    "Uncorrected minimum outdoor airflow rate"
  Buildings.Controls.OBC.CDL.Reals.Divide div1
    "First input divided by second input"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addPar(
    final p=1) "Add parameter"
  Buildings.Controls.OBC.CDL.Reals.Subtract sysVenEff
    "Current system ventilation efficiency"
  Buildings.Controls.OBC.CDL.Reals.Max max1
    "Avoid devide by zero"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant desOutAir(
    final k=VDesTotOutAir_flow)
    "Design total outdoor airflow rate "
  Buildings.Controls.OBC.CDL.Reals.Divide div2 "Division"
  Buildings.Controls.OBC.CDL.Reals.Min min2
    "Uncorrected minimum outdoor airflow rate"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gaiDivZer(
    final k=1E-3)
    "Gain, used to avoid division by zero if the flow rate is smaller than 0.1%"
  Buildings.Controls.OBC.CDL.Reals.Divide norVOutMin
    "Normalization for minimum outdoor air flow rate"
  Buildings.Controls.OBC.CDL.Reals.Divide norVOut
    if (minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
     or minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.SingleDamper)
    "Normalization for outdoor air flow rate"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant neaZer(
    final k=1E-4)
    "Near zero value"
  Buildings.Controls.OBC.CDL.Reals.Max max2
    "Avoid devide by zero"

equation
  connect(VSumAdjPopBreZon_flow, add2.u1)
  connect(VSumAdjAreBreZon_flow, add2.u2)
  connect(add2.y, min1.u1)
  connect(uncDesOutAir.y, min1.u2)
  connect(min1.y, VUncOutAir_flow)
  connect(min1.y, div1.u1)
  connect(div1.y, addPar.u)
  connect(uOutAirFra_max, sysVenEff.u2)
  connect(addPar.y, sysVenEff.u1)
  connect(uncDesOutAir.y, gaiDivZer.u)
  connect(gaiDivZer.y, max1.u1)
  connect(VSumZonPri_flow, max1.u2)
  connect(max1.y, div1.u2)
  connect(min1.y, div2.u1)
  connect(desOutAir.y, min2.u1)
  connect(div2.y, min2.u2)
  connect(min2.y, VEffAirOut_flow_min)
  connect(min2.y, norVOutMin.u1)
  connect(desOutAir.y, norVOutMin.u2)
  connect(norVOutMin.y, effOutAir_normalized)
  connect(norVOut.y, outAir_normalized)
  connect(VAirOut_flow, norVOut.u1)
  connect(desOutAir.y, norVOut.u2)
  connect(sysVenEff.y, max2.u1)
  connect(neaZer.y, max2.u2)
  connect(max2.y, div2.u2)
end AHU;


within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow;
package ASHRAE62_1 "Package of sequences specifying outdoor airflow setpoint by complying with ASHRAE 62.1"
end ASHRAE62_1;


Calculate the sum of zone level setpoints. This sequence sums up zone level minimum outdoor airflow setpoints and find the maximum
outdoor air fraction. It is implemented according to Section 5.16.3.1 of ASHRAE
Guideline G36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.ASHRAE62_1;
block SumZone "Calculate the sum of zone level setpoints"

  parameter Integer nZon
    "Total number of serving zones";
  parameter Integer nGro
    "Total number of groups";
  parameter Integer zonGroMat[nGro, nZon]
    "Zone matrix with zone group as row index and zone as column index. It uses index 1 to flag which zone is in which group";
  parameter Integer zonGroMatTra[nZon, nGro]
    "Transpose of the zone matrix";

  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod[nGro]
    "Groups operation mode"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VAdjPopBreZon_flow[nZon](
    final min=fill(0,nZon),
    final unit=fill("m3/s",nZon),
    final quantity=fill("VolumeFlowRate", nZon))
    "Adjusted population component breathing zone flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VAdjAreBreZon_flow[nZon](
    final min=fill(0,nZon),
    final unit=fill("m3/s",nZon),
    final quantity=fill("VolumeFlowRate", nZon))
    "Adjusted area component breathing zone flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VZonPri_flow[nZon](
    final min=fill(0,nZon),
    final unit=fill("m3/s",nZon),
    final quantity=fill("VolumeFlowRate", nZon))
    "Measured zone primary airflow rates"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VMinOA_flow[nZon](
    final min=fill(0,nZon),
    final unit=fill("m3/s",nZon),
    final quantity=fill("VolumeFlowRate", nZon))
    "Minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VSumAdjPopBreZon_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    "Sum of the adjusted population component breathing zone flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VSumAdjAreBreZon_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    "Sum of the adjusted area component breathing zone flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VSumZonPri_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    "Sum of the zone primary airflow rates for all zones in all zone groups that are in occupied mode"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput uOutAirFra_max(
    final min=0,
    final unit="1")
    "Maximum zone outdoor air fraction"

  Buildings.Controls.OBC.CDL.Reals.MatrixGain groFlo(
    final K=zonGroMat)
    "Vector of total zone flow of each group"
  Buildings.Controls.OBC.CDL.Reals.MatrixGain groFlo1(
    final K=zonGroMat)
    "Vector of total zone flow of each group"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nGro]
    "Convert boolean to real"
  Buildings.Controls.OBC.CDL.Reals.Multiply mul[nGro]
    "Find the total flow of zone group"
  Buildings.Controls.OBC.CDL.Reals.Multiply mul1[nGro]
    "Find the total flow of zone group"
  Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum(
    final nin=nGro)
    "Sum of the adjusted population component breathing zone flow rate"
  Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum1(
    final nin=nGro)
    "Sum of the adjusted area component breathing zone flow rate"
  Buildings.Controls.OBC.CDL.Reals.MatrixGain groFlo2(
    final K=zonGroMat)
    "Vector of total zone flow of each group"
  Buildings.Controls.OBC.CDL.Reals.Multiply mul2[nGro]
    "Find the total flow of zone group"
  Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum2(
    final nin=nGro)
    "Sum of the zone primary airflow rates for all zones in all zone groups that are in occupied mode"
  Buildings.Controls.OBC.CDL.Reals.Divide div1[nZon]
    "Zone outdoor air fraction"
  Buildings.Controls.OBC.CDL.Reals.MatrixGain groFlo3(
    final K=zonGroMatTra)
    "Vector of zones in occupied mode"
  Buildings.Controls.OBC.CDL.Reals.Multiply mul3[nZon]
    "Vector of zone outdoor air fraction"
  Buildings.Controls.OBC.CDL.Reals.MultiMax mulMax(
    final nin=nZon)
    "Maximum zone outdoor air fraction"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant occMod[nGro](
    final k=fill(Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied,nGro))
    "Occupied mode index"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu1[nGro]
    "Check if operation mode is occupied"
  Buildings.Controls.OBC.CDL.Reals.Max max2[nZon] "Avoid devide by zero"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant neaZer[nZon](
    final k=fill(1E-4, nZon))
    "Near zero value"
  Buildings.Controls.OBC.CDL.Reals.Min min1[nZon] "Use smaller value"
equation
  connect(uOpeMod, intEqu1.u1)
  connect(occMod.y, intEqu1.u2)
  connect(VAdjPopBreZon_flow, groFlo.u)
  connect(VAdjAreBreZon_flow, groFlo1.u)
  connect(intEqu1.y, booToRea.u)
  connect(groFlo.y, mul.u2)
  connect(booToRea.y, mul.u1)
  connect(booToRea.y, mul1.u1)
  connect(groFlo1.y, mul1.u2)
  connect(mul.y, mulSum.u)
  connect(mul1.y, mulSum1.u)
  connect(mulSum1.y, VSumAdjAreBreZon_flow)
  connect(mulSum.y, VSumAdjPopBreZon_flow)
  connect(VZonPri_flow, groFlo2.u)
  connect(groFlo2.y, mul2.u2)
  connect(booToRea.y, mul2.u1)
  connect(mul2.y, mulSum2.u)
  connect(mulSum2.y, VSumZonPri_flow)
  connect(booToRea.y, groFlo3.u)
  connect(div1.y, mul3.u2)
  connect(groFlo3.y, mul3.u1)
  connect(mul3.y, mulMax.u)
  connect(mulMax.y, uOutAirFra_max)
  connect(neaZer.y, max2.u2)
  connect(VZonPri_flow, max2.u1)
  connect(max2.y, div1.u2)
  connect(min1.y, div1.u1)
  connect(VMinOA_flow, min1.u2)
  connect(VZonPri_flow, min1.u1)
end SumZone;


Validate the sequences of setting AHU level minimum outdoor airflow rate. This model shows how to compose the subsequences to find the minimum outdoor
airflow setpoint of an AHU unit that serves three zones.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.ASHRAE62_1.Validation;
model OutdoorAirFlow
  "Validate the sequences of setting AHU level minimum outdoor airflow rate"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.ASHRAE62_1.AHU
    ahu(
    final minOADes=Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow,
    final VUncDesOutAir_flow=1.2,
    final VDesTotOutAir_flow=1) "AHU level minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.ASHRAE62_1.SumZone zonToAhu(
    final nZon=nZon,
    final nGro=nGro,
    final zonGroMat=zonGroMat,
    final zonGroMatTra=zonGroMatTra) "From zone level to AHU level"

protected
  parameter Integer nZon=4
    "Total number of zones";
  parameter Integer nGro=2
    "Total number of groups";
  parameter Integer zonGroMat[nGro,nZon]={{1,1,0,0},{0,0,1,1}}
    "Zone matrix with zone group as row index and zone as column index. It flags which zone is grouped in which zone group";
  parameter Integer zonGroMatTra[nZon,nGro]={{1,0},{1,0},{0,1},{0,1}}
    "Transpose of the zone matrix";
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant opeMod[nGro](
    final k={Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied,
             Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.unoccupied})
    "AHU operation mode is Occupied"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant adjPopFlo[nZon](
    final k={0.1,0.12,0.2,0.15})
    "Adjusted population component flow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant adjAreFlo[nZon](
    final k={0.08,0.1,0.15,0.1})
    "Adjusted area component flow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant priFlo[nZon](
    final k={0.3,0.25,0.4,0.5})
    "Measured zone primary airflow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minOAFlo[nZon](
    final k={0.2,0.21,0.35,0.25})
    "Minimum outdoor airflow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant outAirFlo(final k=1)
    "Adjusted area component flow"
equation
  connect(adjPopFlo.y, zonToAhu.VAdjPopBreZon_flow)
  connect(adjAreFlo.y, zonToAhu.VAdjAreBreZon_flow)
  connect(priFlo.y, zonToAhu.VZonPri_flow)
  connect(opeMod.y, zonToAhu.uOpeMod)
  connect(minOAFlo.y, zonToAhu.VMinOA_flow)
  connect(zonToAhu.VSumAdjPopBreZon_flow, ahu.VSumAdjPopBreZon_flow)
  connect(zonToAhu.VSumAdjAreBreZon_flow, ahu.VSumAdjAreBreZon_flow)
  connect(zonToAhu.VSumZonPri_flow, ahu.VSumZonPri_flow)
  connect(zonToAhu.uOutAirFra_max, ahu.uOutAirFra_max)
  connect(outAirFlo.y, ahu.VAirOut_flow)
end OutdoorAirFlow;


Collection of validation models

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.ASHRAE62_1;
package Validation "Collection of validation models"
end Validation;


AHU level setpoint calculation. This sequence outputs AHU level effective outdoor air absolute minimum and design
minimum setpoints VEffAbsOutAir_flow, VEffDesOutAir_flow and
the nomalized minimum setpoint effOutAir_normalized
when complying with California Title 24 ventilation requirements.
It is implemented according to Section 5.16.3.2 of ASHRAE
Guideline G36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.Title24;
block AHU "AHU level setpoint calculation"

  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection minOADes
    "Type of outdoor air section"
  parameter Boolean have_CO2Sen
    "True: there are zones have CO2 sensor";
  parameter Real VAbsOutAir_flow(unit="m3/s")
    "Design outdoor airflow rate when all zones with CO2 sensors or occupancy sensors are unpopulated"
  parameter Real VDesOutAir_flow(unit="m3/s")
    "Design minimum outdoor airflow rate with the areas served by the system are occupied at their design population, including diversity where applicable"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput VSumZonAbsMin_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    "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")
    "Sum of the zone design minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uCO2Loo_max(
    final unit="1")
    if have_CO2Sen "Maximum Zone CO2 control loop"
  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.RealOutput VEffAbsOutAir_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    "Effective outdoor air absolute minimum setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput effAbsOutAir_normalized(
    final unit="1")
    "Effective minimum outdoor airflow setpoint, normalized by the absolute outdoor airflow rate "
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VEffDesOutAir_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    "Effective outdoor air design minimum setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput effDesOutAir_normalized(
    final unit="1")
    "Effective minimum outdoor airflow setpoint, normalized by the design outdoor airflow rate "
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput effOutAir_normalized(
    final unit="1")
    "Effective minimum outdoor airflow setpoint, normalized by the design total outdoor airflow rate "
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput outAir_normalized(
    final unit="1")
    if (minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
     or minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.SingleDamper)
    "Normalized outdoor airflow rate"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant absOutAir(
    final k=VAbsOutAir_flow)
    "Design outdoor airflow rate when all zones with CO2 sensors or occupancy sensors are unpopulated"
  Buildings.Controls.OBC.CDL.Reals.Min min1
    "Effective outdoor air absolute minimum setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant desOutAir(
    final k=VDesOutAir_flow)
    "Design minimum outdoor airflow with areas served by the system are occupied at their design population, including diversity where applicable"
  Buildings.Controls.OBC.CDL.Reals.Min min2 "Effective outdoor air design minimum setpoint"
  Buildings.Controls.OBC.CDL.Reals.Divide norVOutMin
    "Normalization for minimum outdoor air flow rate"
  Buildings.Controls.OBC.CDL.Reals.Divide norVOutMin1
    "Normalization for minimum outdoor air flow rate"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(
    final k=0.5) if have_CO2Sen
    "Constant value"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1(
    final k=1) if have_CO2Sen
    "Constant value"
  Buildings.Controls.OBC.CDL.Reals.Line effOutAir(
    final limitBelow=false,
    final limitAbove=true) if have_CO2Sen
    "Normalized effective outdoor air setpoint"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai(
    final k=1) if not have_CO2Sen
    "When there is no zone has CO2 sensor, design setpoint will be applied"
  Buildings.Controls.OBC.CDL.Reals.Divide norVOutMin2 if have_CO2Sen
    "Normalization for minimum outdoor air flow rate"
  Buildings.Controls.OBC.CDL.Reals.Divide norVOut
    if (minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
     or minOADes == Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.SingleDamper)
    "Normalization for outdoor air flow rate"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant neaZer(
    final k=1E-4)
    "Near zero value"
  Buildings.Controls.OBC.CDL.Reals.Max max2
    "Avoid devide by zero"
  Buildings.Controls.OBC.CDL.Reals.Max max1
    "Avoid devide by zero"
equation
  connect(absOutAir.y, min1.u1)
  connect(min1.y, VEffAbsOutAir_flow)
  connect(desOutAir.y, min2.u1)
  connect(min2.y, VEffDesOutAir_flow)
  connect(VSumZonDesMin_flow, min2.u2)
  connect(VSumZonAbsMin_flow, min1.u2)
  connect(min1.y, norVOutMin1.u1)
  connect(min2.y, norVOutMin.u1)
  connect(norVOutMin1.y, effAbsOutAir_normalized)
  connect(norVOutMin.y, effDesOutAir_normalized)
  connect(uCO2Loo_max, effOutAir.u)
  connect(con.y, effOutAir.x1)
  connect(con1.y, effOutAir.x2)
  connect(gai.y, effOutAir_normalized)
  connect(min2.y, effOutAir.f2)
  connect(min1.y, effOutAir.f1)
  connect(norVOutMin.y, gai.u)
  connect(effOutAir.y, norVOutMin2.u1)
  connect(norVOutMin2.y, effOutAir_normalized)
  connect(VAirOut_flow, norVOut.u1)
  connect(norVOut.y, outAir_normalized)
  connect(max2.y, norVOutMin1.u2)
  connect(neaZer.y, max2.u2)
  connect(absOutAir.y, max2.u1)
  connect(neaZer.y, max1.u2)
  connect(desOutAir.y, max1.u1)
  connect(max1.y, norVOutMin.u2)
  connect(max1.y, norVOutMin2.u2)
  connect(max1.y, norVOut.u2)
end AHU;


Complying California Title 24

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow;
package Title24 "Complying California Title 24"
end Title24;


Sum of the zone level setpoints calculation. This sequence sums up zone level minimum outdoor airflow setpoints when complying
with California Title 24 ventilation requirements. It is implemented according
to Section 5.16.3.2 of ASHRAE Guideline G36, May 2020.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.Title24;
block SumZone "Sum of the zone level setpoints calculation"

  parameter Integer nZon
    "Total number of serving zones";
  parameter Integer nGro
    "Total number of groups";
  parameter Integer zonGroMat[nGro, nZon]
    "Zone matrix with zone group as row index and zone as column index. It flags which zone is grouped in which zone group";
  parameter Boolean have_CO2Sen
    "True: some zones have CO2 sensor";

  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput uOpeMod[nGro]
    "Groups operation mode"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VZonAbsMin_flow[nZon](
    final min=fill(0,nZon),
    final unit=fill("m3/s",nZon),
    final quantity=fill("VolumeFlowRate",nZon))
    "Zone absolute minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VZonDesMin_flow[nZon](
    final min=fill(0,nZon),
    final unit=fill("m3/s",nZon),
    final quantity=fill("VolumeFlowRate",nZon))
    "Zone design minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput uCO2[nZon](
    final unit=fill("1",nZon)) if have_CO2Sen
    "Zone CO2 control loop"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VSumZonAbsMin_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    "Sum of the zone absolute minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VSumZonDesMin_flow(
    final min=0,
    final unit="m3/s",
    final quantity="VolumeFlowRate")
    "Sum of the zone design minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yMaxCO2(
    final unit="1")
    if have_CO2Sen
    "Maximum CO2 control loop signal"

  Buildings.Controls.OBC.CDL.Reals.MatrixGain groFlo(
    final K=zonGroMat)
    "Vector of total zone flow of each group"
  Buildings.Controls.OBC.CDL.Reals.MatrixGain groFlo1(
    final K=zonGroMat)
    "Vector of total zone flow of each group"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nGro]
    "Convert boolean to real"
  Buildings.Controls.OBC.CDL.Reals.Multiply mul[nGro]
    "Find the total flow of zone group"
  Buildings.Controls.OBC.CDL.Reals.Multiply mul1[nGro]
    "Find the total flow of zone group"
  Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum(
    final nin=nGro)
    "Sum of the zone absolute minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum1(
    final nin=nGro)
    "Sum of the zone design minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant occMod[nGro](
    final k=fill(Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied,nGro))
    "Occupied mode index"
  Buildings.Controls.OBC.CDL.Integers.Equal intEqu1[nGro]
    "Check if operation mode is occupied"
  Buildings.Controls.OBC.CDL.Reals.MultiMax mulMax(
    final nin=nZon) if have_CO2Sen
    "Maximum CO2 loop signal"

equation
  connect(uOpeMod, intEqu1.u1)
  connect(occMod.y, intEqu1.u2)
  connect(VZonAbsMin_flow, groFlo.u)
  connect(intEqu1.y, booToRea.u)
  connect(groFlo.y, mul.u2)
  connect(booToRea.y, mul.u1)
  connect(booToRea.y, mul1.u1)
  connect(groFlo1.y, mul1.u2)
  connect(mul.y, mulSum.u)
  connect(mul1.y, mulSum1.u)
  connect(VZonDesMin_flow, groFlo1.u)
  connect(mulSum.y, VSumZonAbsMin_flow)
  connect(mulSum1.y, VSumZonDesMin_flow)
  connect(uCO2, mulMax.u)
  connect(mulMax.y, yMaxCO2)
end SumZone;


within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.Title24.Validation;
model OutdoorAirFlow
  "Validate the sequences of setting AHU level minimum outdoor airflow rate"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.Title24.AHU
    ahu(
    final minOADes=Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow,
    final have_CO2Sen=have_CO2Sen,
    final VAbsOutAir_flow=0.5,
    final VDesOutAir_flow=1) "AHU level minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.Title24.SumZone zonToAhu(
    final nZon=nZon,
    final nGro=nGro,
    final zonGroMat=zonGroMat,
    final have_CO2Sen=have_CO2Sen) "From zone level to AHU level"

protected
  parameter Boolean have_CO2Sen=true
    "True: there are zones have CO2 sensor";
  parameter Integer nZon=4
    "Total number of zones";
  parameter Integer nGro=2
    "Total number of groups";
  parameter Integer zonGroMat[nGro,nZon]={{1,1,0,0},{0,0,1,1}}
    "Zone matrix with zone group as row index and zone as column index. It flags which zone is grouped in which zone group";
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant opeMod[nGro](
    final k={Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied,
             Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.unoccupied})
    "AHU operation mode is Occupied"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zonAbsMinFlo[nZon](
      final k={0.1,0.12,0.2,0.15}) "Zone absolute minimum flow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zonDesMinFlo[nZon](
      final k={0.15,0.2,0.25,0.3}) "Adjusted area component flow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant co2Loo[nZon](
    final k={0.3,0.25,0.4,0.5}) "Zone CO2 loop signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant outAirFlo(final k=1)
    "Adjusted area component flow"
equation
  connect(opeMod.y, zonToAhu.uOpeMod)
  connect(zonAbsMinFlo.y, zonToAhu.VZonAbsMin_flow)
  connect(zonDesMinFlo.y, zonToAhu.VZonDesMin_flow)
  connect(co2Loo.y, zonToAhu.uCO2)
  connect(zonToAhu.VSumZonAbsMin_flow, ahu.VSumZonAbsMin_flow)
  connect(zonToAhu.VSumZonDesMin_flow, ahu.VSumZonDesMin_flow)
  connect(zonToAhu.yMaxCO2, ahu.uCO2Loo_max)
  connect(outAirFlo.y, ahu.VAirOut_flow)
end OutdoorAirFlow;


Collection of validation models

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.Title24;
package Validation "Collection of validation models"
end Validation;


Validate model for implementing freeze protection. This example validates

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.FreezeProtection
for air handling unit serving multiple zones.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.Validation;
model FreezeProtection
  "Validate model for implementing freeze protection"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.FreezeProtection
    frePro(
    final buiPreCon=Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefDamper,

    final minOADes=Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow,

    final freSta=Buildings.Controls.OBC.ASHRAE.G36.Types.FreezeStat.No_freeze_stat)
    "Freeze protection control"

  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp outDamPos(
    final height=0.5,
    final offset=0.1,
    final duration=3600) "Outdoor air damper position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant outDamPosMin(
    final k=0.1)
    "Outdoor air damper minimum position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp heaCoiPos(
    final height=0.46,
    final offset=0.5,
    final duration=3600) "Heating coil position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minOutDamPos(
    final k=0.15)
    "Minimum outdoor air damper position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp retDamPos(
    final height=0.2,
    final offset=0.7,
    final duration=3600) "Return air damper position"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse freRes(
    final width=0.95,
    final period=3600)
    "Freeze protection reset"
  Buildings.Controls.OBC.CDL.Logical.Not not1
    "Logical not"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp supFanSpe(
    final height=0.2,
    final offset=0.5,
    final duration=3600) "Supply fan speed"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp cooCoiPos(
    final height=0.2,
    final offset=0.5,
    final duration=3600) "Cooling coil position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp supTem(
    final height=-4,
    final offset=273.15 + 6,
    final duration=3600) "Supply air temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp mixTem(
    final height=-5,
    final offset=273.15 + 8,
    final duration=3600) "Mixed air temperature"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr(
    final h=0.01)
    "Check if the supply fan is proven on"
equation
  connect(freRes.y, not1.u)
  connect(outDamPosMin.y,frePro. uOutDamPosMin)
  connect(outDamPos.y, frePro.uOutDam)
  connect(heaCoiPos.y,frePro. uHeaCoi)
  connect(minOutDamPos.y, frePro.uMinOutDam)
  connect(retDamPos.y, frePro.uRetDam)
  connect(supTem.y, frePro.TAirSup)
  connect(not1.y, frePro.u1SofSwiRes)
  connect(supFanSpe.y, frePro.uSupFan)
  connect(cooCoiPos.y,frePro. uCooCoi)
  connect(mixTem.y, frePro.TAirMix)
  connect(supFanSpe.y, greThr.u)
  connect(greThr.y, frePro.u1SupFan)
end FreezeProtection;


Validate model for disabling freeze protection. This example validates

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.FreezeProtection
for air handling unit serving multiple zones, when disabling the freeze protection.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.Validation;
model FreezeProtection_Disable
  "Validate model for disabling freeze protection"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.FreezeProtection
    frePro(
    final have_frePro=false,
    final buiPreCon=Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefDamper,

    final minOADes=Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow,

    final freSta=Buildings.Controls.OBC.ASHRAE.G36.Types.FreezeStat.No_freeze_stat)
    "Freeze protection control"

  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp outDamPos(
    final height=0.5,
    final offset=0.1,
    final duration=3600) "Outdoor air damper position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp heaCoiPos(
    final height=0.46,
    final offset=0.5,
    final duration=3600) "Heating coil position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minOutDamPos(
    final k=0.15)
    "Minimum outdoor air damper position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp retDamPos(
    final height=0.2,
    final offset=0.7,
    final duration=3600) "Return air damper position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp supFanSpe(
    final height=0.2,
    final offset=0.5,
    final duration=3600) "Supply fan speed"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp cooCoiPos(
    final height=0.2,
    final offset=0.5,
    final duration=3600) "Cooling coil position"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr(
    final h=0.01)
    "Check if the supply fan is proven on"
equation
  connect(outDamPos.y, frePro.uOutDam)
  connect(heaCoiPos.y,frePro. uHeaCoi)
  connect(minOutDamPos.y, frePro.uMinOutDam)
  connect(retDamPos.y, frePro.uRetDam)
  connect(supFanSpe.y, frePro.uSupFan)
  connect(cooCoiPos.y,frePro. uCooCoi)
  connect(supFanSpe.y, greThr.u)
  connect(greThr.y, frePro.u1SupFan)
end FreezeProtection_Disable;


Collection of validation models

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints;
package Validation "Collection of validation models"
end Validation;


Validate model for calculating the plant requests. This example validates

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.PlantRequests
for air handling unit serving multiple zones.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.Validation;
model PlantRequests
  "Validate model for calculating the plant requests"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.PlantRequests plaReq
    "Calculate plant request"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.PlantRequests plaReq1(
    heaCoi=Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.None)
    "Calculate plant request"

  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp supTem(
    final height=8,
    final offset=273.15 + 15,
    final duration=3600) "Supply air temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp supTemSet(
    final height=6,
    final offset=273.15 + 14.5,
    final duration=3600) "Supply air temperature setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp cooCoi(
    final height=-0.3,
    final offset=0.96,
    final duration=3600,
    startTime=1000) "Cooling coil position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp heaCoi(
    final height=-0.3,
    final offset=0.96,
    final duration=3600,
    startTime=1000) "Heating coil position"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp supTem1(
    final height=8,
    final offset=273.15 + 12,
    final duration=3600) "Supply air temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp supTemSet1(
    final height=15,
    final offset=273.15 + 20,
    final duration=3600) "Supply air temperature setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant cooCoi1(
    final k=0) "Cooling coil position"

equation
  connect(supTem.y, plaReq1.TAirSup)
  connect(supTemSet.y, plaReq1.TAirSupSet)
  connect(cooCoi.y, plaReq1.uCooCoiSet)
  connect(supTem1.y, plaReq.TAirSup)
  connect(supTemSet1.y, plaReq.TAirSupSet)
  connect(cooCoi1.y, plaReq.uCooCoiSet)
  connect(heaCoi.y, plaReq.uHeaCoiSet)
end PlantRequests;


Validate model for calculating relief damper control. This example validates

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefDamper
for actuated relief damper control without fan
for systems with multiple
zones.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.Validation;
model ReliefDamper
  "Validate model for calculating relief damper control"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefDamper relDam(
    final k=0.1) "Relief damper control"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefDamper relDam1
    "Relief damper control"

  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse yFan(
    final period=4000) "Supply fan status"

  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp dpBui(
    final height=40,
    final offset=0,
    final duration=1800) "Building static presure"

equation
  connect(yFan.y, relDam.u1SupFan)
  connect(dpBui.y, relDam.dpBui)
  connect(yFan.y, relDam1.u1SupFan)
  connect(dpBui.y, relDam1.dpBui)
end ReliefDamper;


Validate model for controlling relief fan. This example validates

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefFan
for controlling relief fan that is part of AHU.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.Validation;
model ReliefFan "Validate model for controlling relief fan"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefFan
    relFanCon(
    final k=0.5) "Open relief damper"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefFan
    relFanCon1 "Turning on relief fan"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefFan
    relFanCon2 "Turning off relief fan"

  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse supFan(final width=0.8,
      final period=3600)
    "Supply fan status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp dpBui(
    final height=40,
    final offset=0,
    final duration=1800) "Building static presure"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp dpBui1(
    final height=-15,
    final offset=20,
    final duration=1800,
    startTime=1800)
    "Building static presure"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant supFan1(
    final k=true)
    "Supply fan status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp dpBui2(
    final height=3,
    final offset=11,
    final duration=1800)
    "Building static presure"

equation
  connect(dpBui.y, relFanCon1.dpBui)
  connect(dpBui1.y, relFanCon2.dpBui)
  connect(supFan.y, relFanCon.u1SupFan)
  connect(supFan1.y, relFanCon1.u1SupFan)
  connect(supFan1.y, relFanCon2.u1SupFan)
  connect(dpBui2.y, relFanCon.dpBui)
end ReliefFan;


Validate model for controlling relief fans group. This example validates

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefFanGroup
for relief fan group for systems with multiple zones.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.Validation;
model ReliefFanGroup
  "Validate model for controlling relief fans group"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefFanGroup
    relFanCon(final k=0.5) "Relief damper control, with staging up fans"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefFanGroup
    relFanCon1 "Relief damper control, with staging up fans and the fan alarm"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReliefFanGroup
    relFanCon2 "Relief damper control, with the staging up and down fans"

  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse supFan1(
    final width=1,
    final period=4000)
    "Supply fan status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp dpBui(
    final height=40,
    final offset=0,
    final duration=1800) "Building static presure"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse supFan2(
    final width=1,
    final period=4000,
    shift=600) "Supply fan status"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr[4](
    final t=fill(0.01, 4))
    "Check if the relief fan is proven on"
  Buildings.Controls.OBC.CDL.Logical.Pre pre[4] "Return relief fan status"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr1[4](
    final t=fill(0.01, 4))
    "Check if the relief fan is proven on"
  Buildings.Controls.OBC.CDL.Logical.Pre pre1[4] "Return relief fan status"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt[4](
    final k=fill(0, 4)) "Constant zero"
  Buildings.Controls.OBC.CDL.Integers.Sources.Pulse intPul(
    final amplitude=2,
    final period=3600,
    final offset=0) "Fan 1 alarm level"
  Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol[4](
    final samplePeriod=fill(20, 4))
    "Zero order hold"
  Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol1[4](
    final samplePeriod=fill(20, 4))
    "Zero order hold"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr2[4](
    final t=fill(0.01, 4))
    "Check if the relief fan is proven on"
  Buildings.Controls.OBC.CDL.Logical.Pre pre2[4] "Return relief fan status"
  Buildings.Controls.OBC.CDL.Discrete.ZeroOrderHold zerOrdHol2[4](
    final samplePeriod=fill(20, 4))
    "Zero order hold"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp dpBui1(
    final height=-15,
    final offset=20,
    final duration=1800,
    startTime=1800)
    "Building static presure"

equation
  connect(dpBui.y, relFanCon.dpBui)
  connect(dpBui.y, relFanCon1.dpBui)
  connect(greThr.y, pre.u)
  connect(supFan1.y, relFanCon.u1SupFan[1])
  connect(supFan2.y, relFanCon.u1SupFan[2])
  connect(supFan1.y, relFanCon1.u1SupFan[1])
  connect(supFan2.y, relFanCon1.u1SupFan[2])
  connect(pre.y, relFanCon.u1RelFan)
  connect(greThr1.y, pre1.u)
  connect(pre1.y, relFanCon1.u1RelFan)
  connect(conInt.y, relFanCon.uRelFanAla)
  connect(conInt[1].y, relFanCon1.uRelFanAla[2])
  connect(conInt[2].y, relFanCon1.uRelFanAla[3])
  connect(conInt[3].y, relFanCon1.uRelFanAla[4])
  connect(intPul.y, relFanCon1.uRelFanAla[1])
  connect(relFanCon.yRelFan, zerOrdHol.u)
  connect(zerOrdHol.y, greThr.u)
  connect(relFanCon1.yRelFan, zerOrdHol1.u)
  connect(zerOrdHol1.y, greThr1.u)
  connect(greThr2.y,pre2. u)
  connect(pre2.y,relFanCon2. u1RelFan)
  connect(relFanCon2.yRelFan, zerOrdHol2.u)
  connect(zerOrdHol2.y,greThr2. u)
  connect(dpBui1.y, relFanCon2.dpBui)
  connect(supFan1.y, relFanCon2.u1SupFan[1])
  connect(supFan2.y, relFanCon2.u1SupFan[2])
  connect(conInt.y, relFanCon2.uRelFanAla)
end ReliefFanGroup;


Validate model for controlling return fan of units using return fan with airflow tracking. This example validates

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReturnFanAirflowTracking
for return fan control with airflow tracking
for systems with multiple
zones.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.Validation;
model ReturnFanAirflowTracking
  "Validate model for controlling return fan of units using return fan with airflow tracking"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReturnFanAirflowTracking
    retFanAirTra(final difFloSet=0.5, final k=0.1)
    "Return fan control with airflow tracking"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReturnFanAirflowTracking
    retFanAirTra1(final difFloSet=0.5)
    "Return fan control with airflow tracking"

  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse yFan(width=0.75,
    final period=4000) "Supply fan status"

  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp supFlo(
    final height=1.0,
    final offset=0.2,
    final duration=1800) "Supply air flow rate"

  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp retFlo(
    final height=0.4,
    final offset=0.1,
    final duration=1800) "Return air flow rate"

equation
  connect(yFan.y, retFanAirTra.u1SupFan)
  connect(yFan.y, retFanAirTra1.u1SupFan)
  connect(supFlo.y, retFanAirTra.VAirSup_flow)
  connect(supFlo.y, retFanAirTra1.VAirSup_flow)
  connect(retFlo.y, retFanAirTra.VAirRet_flow)
  connect(retFlo.y, retFanAirTra1.VAirRet_flow)
end ReturnFanAirflowTracking;


Validate model for calculating return fan control with direct building pressure of multi zone VAV AHU. This example validates

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReturnFanDirectPressure
for exhaust air damper and return fan control with direct building pressure measurement
for systems with multiple
zones.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.Validation;
model ReturnFanDirectPressure
  "Validate model for calculating return fan control with direct building pressure of multi zone VAV AHU"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReturnFanDirectPressure retFanPre(
    final disSpe_min=0.1,
    final disSpe_max=0.9,
    final k=0.1) "Return fan control with direct building pressure"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReturnFanDirectPressure retFanPre1(
    final disSpe_min=0.1,
    final disSpe_max=0.9,
    final k=0.5) "Return fan control with direct building pressure"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.ReturnFanDirectPressure retFanPre2(final
      disSpe_min=0.1, final disSpe_max=0.9)
    "Return fan control with direct building pressure"

  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse yFan(
    final period=4000) "Supply fan status"

  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp dpBui(
    final height=40,
    final offset=0,
    final duration=1800) "Building static presure"

equation
  connect(yFan.y, retFanPre.u1SupFan)
  connect(dpBui.y, retFanPre.dpBui)
  connect(yFan.y, retFanPre1.u1SupFan)
  connect(yFan.y, retFanPre2.u1SupFan)
  connect(dpBui.y, retFanPre1.dpBui)
  connect(dpBui.y, retFanPre2.dpBui)
  connect(yFan.y, retFanPre.u1MinOutAirDam)
  connect(yFan.y, retFanPre1.u1MinOutAirDam)
  connect(yFan.y, retFanPre2.u1MinOutAirDam)
end ReturnFanDirectPressure;


Validate SupplyFan. This example validates

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.SupplyFan.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.Validation;
model SupplyFan "Validate SupplyFan"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.SupplyFan conSupFan(
    final Td=1,
    final controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    final maxSet=400,
    final k=0.001,
    final Ti=10) "Block outputs supply fan speed"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.SupplyFan conSupFan1(
    final have_perZonRehBox=true,
    final Td=1,
    final controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    final maxSet=400,
    final k=0.001,
    final Ti=10)
    "Block outputs supply fan speed for the AHU system with reheat boxes on perimeter zones"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.SupplyFan conSupFan2(
    final Td=1,
    final controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    final maxSet=400,
    final k=0.001,
    final Ti=10)
    "Block outputs supply fan speed for the unit with airflow measurement station"

protected
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp ram(
    final duration=28800,
    final height=6) "Ramp signal for generating operation mode"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin sine(
    final freqHz=1/14400,
    final offset=3,
    final amplitude=2)
    "Generate sine signal "
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin sine1(
    final freqHz=1/14400,
    final offset=200,
    amplitude=150)
    "Generate sine signal"
  Buildings.Controls.OBC.CDL.Reals.Abs abs
    "Block generates absolute value of input"
  Buildings.Controls.OBC.CDL.Reals.Abs abs1
    "Block generates absolute value of input"
  Buildings.Controls.OBC.CDL.Reals.Round round2(
    final n=0)
    "Round real number to given digits"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1
    "Convert real to integer"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2
    "Convert real to integer"
  Buildings.Controls.OBC.CDL.Reals.Round round1(n=0)
    "Round real number to given digits"

equation
  connect(sine1.y, conSupFan.dpDuc)
  connect(sine.y, abs1.u)
  connect(ram.y, abs.u)
  connect(abs1.y, round2.u)
  connect(round2.y, reaToInt1.u)
  connect(reaToInt1.y, conSupFan.uZonPreResReq)
  connect(abs.y, round1.u)
  connect(round1.y, reaToInt2.u)
  connect(reaToInt2.y, conSupFan.uOpeMod)
  connect(reaToInt2.y, conSupFan2.uOpeMod)
  connect(reaToInt1.y, conSupFan2.uZonPreResReq)
  connect(sine1.y, conSupFan2.dpDuc)
  connect(reaToInt2.y, conSupFan1.uOpeMod)
  connect(reaToInt1.y, conSupFan1.uZonPreResReq)
  connect(sine1.y, conSupFan1.dpDuc)
end SupplyFan;


Validate model for controlling coil valve postion of multi zone VAV AHU. This example validates

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.SupplySignals
for a change of the supply air temperature setpoint, measured supply air temperature and
the supply fan status, to specify coil valve positions, and generate control
loop signal.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.Validation;
model SupplySignals
  "Validate model for controlling coil valve postion of multi zone VAV AHU"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.SupplySignals supSig
    "Output valve position and supply air temperature control loop signal"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse supFanSta(period=7200)
    "Supply fan status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Pulse TSup(
    final amplitude=14,
    final period=7200,
    final offset=10 + 273.15)
    "Supply air temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TSupSet(
    final height=3,
    final duration=7200,
    final offset=15 + 273.15)
    "Supply air temperature setpoint"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.SupplySignals supSig1
    "Output valve position and supply air temperature control loop signal"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant fanOn(
    final k=true) "Fan on"

equation
  connect(TSupSet.y, supSig.TAirSupSet)
  connect(TSup.y, supSig.TAirSup)
  connect(supFanSta.y, supSig.u1SupFan)
  connect(TSupSet.y, supSig1.TAirSupSet)
  connect(TSup.y, supSig1.TAirSup)
  connect(fanOn.y, supSig1.u1SupFan)
end SupplySignals;


Validate model for calculating supply air temperature of multi zone VAV AHU. This example validates

Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.SupplyTemperature
for a change of outdoor temperature, operation mode, supply fan status, maximum
supply temperature, to specify the supply air temperature for systems with multiple
zones.

within Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.Validation;
model SupplyTemperature
  "Validate model for calculating supply air temperature of multi zone VAV AHU"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.SupplyTemperature conTSupSet
    "Supply air temperature setpoint for multi zone system"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin outTem(
    final amplitude=5,
    final freqHz=1/86400,
    final offset=18 + 273.15) "Outdoor air temperature"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse supFanSta(
    final period=43200)
    "Supply fan status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp opeMod(
    final offset=1,
    final height=1,
    final duration=90000) "Operation mode"
  Buildings.Controls.OBC.CDL.Reals.Abs abs
    "Block generates absolute value of input"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin sine(
    final amplitude=6,
    final freqHz=1/86400)
    "Block generates sine signal"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt1
    "Convert real to integer"
  Buildings.Controls.OBC.CDL.Reals.Round round1(
    final n=0)
    "Round real number to given digits"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reaToInt2
    "Convert real to integer"
  Buildings.Controls.OBC.CDL.Reals.Round round2(
    final n=0)
    "Round real number to given digits"

equation
  connect(supFanSta.y, conTSupSet.u1SupFan)
  connect(outTem.y, conTSupSet.TOut)
  connect(sine.y, abs.u)
  connect(opeMod.y, round2.u)
  connect(round2.y, reaToInt2.u)
  connect(abs.y, round1.u)
  connect(round1.y, reaToInt1.u)
  connect(reaToInt1.y, conTSupSet.uZonTemResReq)
  connect(reaToInt2.y, conTSupSet.uOpeMod)
end SupplyTemperature;