Interface class for plant controller. This block serves as an interface class for the plant controller.

within Buildings.DHC.Plants.Combined.Controls.BaseClasses;
block PartialController "Interface class for plant controller"

  parameter Integer nChi(final min=1, start=1)
    "Number of units operating at design conditions"
  parameter Integer nPumChiWat(final min=1, start=1)
    "Number of CHW pumps operating at design conditions"
  parameter Modelica.Units.SI.Temperature TChiWatSup_nominal
    "Design (minimum) CHW supply temperature"

  parameter Integer nChiHea(final min=1, start=1)
    "Number of units operating at design conditions"
  parameter Integer nPumHeaWat(final min=1, start=1)
    "Number of HW pumps operating at design conditions"
  parameter Modelica.Units.SI.Temperature THeaWatSup_nominal
    "Design (maximum) HW supply temperature"

  parameter Integer nHeaPum(final min=1, start=1)
    "Number of heat pumps operating at design conditions"
  parameter Integer nPumConWatCon(final min=1, start=1)
    "Number of CW pumps serving condenser barrels at design conditions"
  parameter Integer nPumConWatEva(final min=1, start=1)
    "Number of CW pumps serving evaporator barrels at design conditions"

  parameter Integer nCoo(final min=1, start=1)
    "Number of cooling tower cells operating at design conditions"
  parameter Integer nPumConWatCoo(final min=1, start=1)
    "Number of CW pumps serving cooling towers at design conditions"

  parameter Modelica.Units.SI.HeatFlowRate QChiWatChi_flow_nominal
    "Cooling design heat flow rate of cooling-only chillers (all units)"
  parameter Modelica.Units.SI.HeatFlowRate QHeaPum_flow_nominal
    "Heating design heat flow rate of heat pumps (all units)"
  parameter Real PLRStaTra(final unit="1", final min=0, final max=1) = 0.85
    "Part load ratio triggering stage transition";
  parameter Modelica.Units.SI.HeatFlowRate QChiWatCasCoo_flow_nominal
    "Cooling design heat flow rate of HRC in cascading cooling mode (all units)"
  parameter Modelica.Units.SI.HeatFlowRate QChiWatCasCoo_flow_nominal_approx
    "Cooling design heat flow rate of HRC in cascading cooling mode (all units), approximate for scaling"
  final parameter Modelica.Units.SI.HeatFlowRate QChiWat_flow_nominal=
    QChiWatChi_flow_nominal+QChiWatCasCoo_flow_nominal
    "Plant cooling design heat flow rate (all units)";
  parameter Modelica.Units.SI.HeatFlowRate QHeaWat_flow_nominal
    "Heating design heat flow rate (all units)"
  parameter Modelica.Units.SI.SpecificHeatCapacity cp_default=
    Buildings.Utilities.Psychrometrics.Constants.cpWatLiq
    "Specific heat capacity of the fluid";

  parameter Modelica.Units.SI.MassFlowRate mChiWat_flow_nominal(
    final min=0)
    "CHW design mass flow rate (all units)"
  parameter Modelica.Units.SI.PressureDifference dpChiWatSet_max(
    final min=0,
    displayUnit="Pa")
    "Design (maximum) CHW differential pressure setpoint"
  parameter Modelica.Units.SI.MassFlowRate mHeaWat_flow_nominal
    "HW design mass flow rate (all units)"
  parameter Modelica.Units.SI.PressureDifference dpHeaWatSet_max(
    final min=0,
    displayUnit="Pa")
    "Design (maximum) HW differential pressure setpoint"
  parameter Modelica.Units.SI.MassFlowRate mConWatCon_flow_nominal(
    final min=0)
    "Design total CW mass flow rate through condenser barrels (all units)"
  parameter Modelica.Units.SI.MassFlowRate mConWatEva_flow_nominal(
    final min=0)
    "Design total CW mass flow rate through evaporator barrels (all units)"

  parameter Modelica.Units.SI.MassFlowRate mChiWatChi_flow_nominal
    "Chiller CHW design mass flow rate (each unit)"
  parameter Modelica.Units.SI.MassFlowRate mChiWatChi_flow_min
    "Chiller CHW minimum mass flow rate (each unit)"
  parameter Modelica.Units.SI.MassFlowRate mConWatChi_flow_nominal
    "Chiller CW design mass flow rate (each unit)"
  parameter Modelica.Units.SI.MassFlowRate mChiWatChiHea_flow_nominal
    "HRC CHW design mass flow rate (each unit)"
  parameter Modelica.Units.SI.MassFlowRate mChiWatChiHea_flow_min
    "HRC CHW minimum mass flow rate (each unit)"
  parameter Modelica.Units.SI.MassFlowRate mConWatChiHea_flow_nominal
    "HRC CW design mass flow rate (each unit)"
  parameter Modelica.Units.SI.MassFlowRate mHeaWatChiHea_flow_min
    "Chiller HW minimum mass flow rate (each unit)"

  parameter Modelica.Units.SI.PressureDifference dpEvaChi_nominal(
    final min=0,
    displayUnit="Pa")
    "Chiller evaporator design pressure drop (each unit)"
  parameter Modelica.Units.SI.PressureDifference dpValEvaChi_nominal(
    final min=0,
    displayUnit="Pa")
    "Chiller evaporator isolation valve design pressure drop (each unit)"
  parameter Modelica.Units.SI.PressureDifference dpEvaChiHea_nominal(
    final min=0,
    displayUnit="Pa")
    "Design chiller evaporator  pressure drop (each unit)"
  parameter Modelica.Units.SI.PressureDifference dpValEvaChiHea_nominal(
    final min=0,
    displayUnit="Pa")
    "HRC evaporator isolation valve design pressure drop (each unit)"

  parameter Modelica.Units.SI.PressureDifference dpConWatConSet_max(
    final min=0,
    displayUnit="Pa")
    "Design (maximum) CW condenser loop differential pressure setpoint"
  parameter Modelica.Units.SI.PressureDifference dpConWatEvaSet_max(
    final min=0,
    displayUnit="Pa")
    "Design (maximum) CW evaporator loop differential pressure setpoint"

  parameter Modelica.Units.SI.Temperature TTanSet[2, 2]
    "Tank temperature setpoints: 2 cycles with 2 setpoints"
  parameter Real fraUslTan(final unit="1", final min=0, final max=1)
    "Useless fraction of TES"
  parameter Integer nTTan(final min=0)=0
    "Number of tank temperature points"
  parameter Real ratFraChaTanLim[5](each final unit="1/h")=
    {-0.3, -0.2, -0.15, -0.10, -0.08}
    "Rate of change of tank charge fraction (over 10, 30, 120, 240, and 360') that triggers Charge Assist (<0)"

  parameter Modelica.Units.SI.TemperatureDifference dTLifChi_min
    "Minimum chiller lift at minimum load"
  parameter Modelica.Units.SI.TemperatureDifference dTLifChi_nominal
    "Design chiller lift"

  parameter Modelica.Units.SI.TemperatureDifference dTHexCoo_nominal
    "Design heat exchanger approach"

  parameter Modelica.Units.SI.Time riseTime=30
    "Time needed to change motor speed between zero and full speed"
  parameter Modelica.Units.SI.Time strokeTime=120
    "Valve stroke time"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Coo
    "Cooling enable signal"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Hea
    "Heating enable signal"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet(final unit="K",
      displayUnit="degC") "CHW supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatSupSet(final unit="K",
      displayUnit="degC")
    "HW supply temperature setpoint"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValEvaChi[nChi]
    "Cooling-only chiller evaporator isolation valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValConChi[nChi](
    each final unit="1")
    "Cooling-only chiller condenser isolation valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Chi[nChi]
    "Cooling-only chiller On/Off command"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumChiWat[nPumChiWat]
    "CHW pump Start command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumChiWat(
    final unit="1")
    "CHW pump speed signal"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValEvaChiHea[nChiHea](
    each final unit="1") "HRC evaporator isolation valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ChiHea[nChiHea]
    "HRC On/Off command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1CooChiHea[nChiHea]
    "HRC cooling mode switchover command: true for cooling, false for heating"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValConChiHea[nChiHea](
    each final unit="1") "HRC condenser isolation valve commanded position"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumHeaWat[nPumHeaWat]
    "HW pump Start command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumHeaWat(
    final unit="1")
    "HW pump speed signal"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValChiWatMinByp(
    final unit="1")
    "CHW minimum flow bypass valve control signal"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValHeaWatMinByp(
    final unit="1") "HW minimum flow bypass valve control signal"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumConWatCon[nPumConWatCon]
    "CW pump serving condenser barrels Start command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumConWatCon(
    final unit="1")
    "CW pump serving condenser barrels Speed command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumConWatEva[nPumConWatEva]
    "CW pump serving evaporator barrels Start command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumConWatEva(
    final unit="1")
    "CW pump serving evaporator barrels Speed command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1HeaPum[nHeaPum]
    "Heat pump On/Off command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput THeaPumSet(
    final unit="K", displayUnit="degC") "Heat pump supply temperature setpoint"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValBypTan(
    final unit="1") "TES tank bypass valve commanded position"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Coo[nCoo]
    "Cooling tower Start command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yCoo(
    final unit="1") "Cooling tower fan speed command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumConWatCoo[
    nPumConWatCoo] "Cooling tower pump Start command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TChiHeaSet[nChiHea](
    each final unit="K", each displayUnit="degC")
    "HRC supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1HeaCooChiHea[nChiHea]
    "HRC direct heat recovery switchover command: true for direct HR, false for cascading"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatSet(final unit="Pa",
      final min=0) "CHW differential pressure setpoint (for local dp sensor)"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHeaWatSet(final unit="Pa",
      final min=0)
    "HW differential pressure setpoint (for local dp sensor)"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWat(final unit="Pa")
    "CHW differential pressure (from local dp sensor)"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHeaWat(final unit="Pa")
    "HW differential pressure (from local dp sensor)"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mChiWatPri_flow(final unit=
        "kg/s") "Primary CHW mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mHeaWatPri_flow(final unit=
        "kg/s") "Primary HW mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpConWatCon(final unit="Pa")
    "CW condenser loop differential pressure"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpConWatEva(final unit="Pa")
    "CW evaporator loop differential pressure"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mConWatCon_flow(final unit=
        "kg/s") "CW condenser loop mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mConWatEva_flow(final unit=
        "kg/s") "CW evaporator loop mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup(final unit="K",
      displayUnit="degC") "CHW supply temperature "
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatPriRet(final unit="K",
      displayUnit="degC") "Primary CHW return temperature "
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatPriRet(final unit="K",
      displayUnit="degC") "Primary HW return temperature "
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TTan[nTTan](
    each final unit="K",
    each  displayUnit="degC")
    "TES tank temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mConWatHexCoo_flow(final unit
      ="kg/s") "CW mass flow rate through secondary (plant) side of HX"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mConWatOutTan_flow(final unit
      ="kg/s")
    "Mass flow rate out of lower port of TES tank (>0 when charging)"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mEvaChi_flow[nChi](
    each final unit="kg/s")
    "Chiller evaporator barrel mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mConChi_flow[nChi](
    each final unit="kg/s")
    "Chiller condenser barrel mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mEvaChiHea_flow[nChiHea](
    each final unit="kg/s")
    "HRC evaporator barrel mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mConChiHea_flow[nChiHea](
    each final unit="kg/s")
    "HRC condenser barrel mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValEvaSwiHea[nChiHea](
    each final unit="1")
    "HRC evaporator switchover valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValConSwiChiHea[nChiHea](
    each final unit="1")
    "HRC condenser switchover valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TEvaLvgChiHea[nChiHea](
    each final unit="K", each displayUnit="degC")
    "HRC evaporator barrel leaving temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatSup(
    final unit="K",
    displayUnit="degC") "HW supply temperature "
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumConWatCoo
    "Cooling tower pump speed command"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatConChiEnt(final unit=
        "K", displayUnit="degC") "Chiller and HRC entering CW temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatConChiLvg(final unit=
        "K", displayUnit="degC") "Chiller and HRC leaving CW temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatCooSup(final unit="K",
      displayUnit="degC") "Cooling tower loop CW supply temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatCooRet(final unit="K",
      displayUnit="degC") "Cooling tower loop CW return temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatHexCooEnt(final unit="K",
      displayUnit="degC")        "HX entering CW temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatHexCooLvg(final unit="K",
      displayUnit="degC")        "HX leaving CW temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConEntChiHea[nChiHea](each final
            unit="K", each displayUnit="degC")
    "HRC condenser barrel entering temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConLvgChiHea[nChiHea](each final
            unit="K", each displayUnit="degC")
    "HRC condenser barrel leaving temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatEvaEnt(final unit="K",
      displayUnit="degC") "HRC evaporator entering CW temperature "
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValConWatEvaMix
    "HRC evaporator CW mixing valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatConRet(final unit
      ="K", displayUnit="degC") "Condenser loop CW return temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConLvgChi[nChi](each final
      unit="K", each displayUnit="degC")
    "Chiller condenser barrel leaving temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValConWatByp(final unit="1")
    "CW chiller bypass valve control signal"
end PartialController;


Block that computes the stage index out of staging signals. This block is used to compute the stage index of the plant or
of multiple lead/lag units such as pump groups.

within Buildings.DHC.Plants.Combined.Controls.BaseClasses;
block StageIndex
  "Block that computes the stage index out of staging signals"

  parameter Integer nSta(start=1)
    "Number of stages"
  parameter Modelica.Units.SI.Time tSta=0
    "Minimum runtime of each stage"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1
    "Enable signal"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Up
    "Staging up signal"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Dow
    "Staging down signal"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput idxSta
    "Stage index"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput preIdxSta
    "Left limit (in discrete-time) of stage index"

  Modelica.StateGraph.InitialStepWithSignal sta0(
    final nOut=1,
    final nIn=nSta+1)
    "Stage 0: no unit"
  Modelica.StateGraph.StepWithSignal sta[nSta](
    each final nIn=2, each final nOut=3)
    "Stage i"
  Modelica.StateGraph.TransitionWithSignal enaLea(
    final enableTimer=false) "Transition enabling lead unit"
  inner Modelica.StateGraph.StateGraphRoot stateGraphRoot "State graph root"
  Modelica.StateGraph.TransitionWithSignal enaLag[nSta](
    each final enableTimer=false)
    "Transition enabling lag unit"
  Buildings.Controls.OBC.CDL.Logical.Timer tim[nSta](each final t=tSta)
    "Timer for minimum runtime"
  Buildings.Controls.OBC.CDL.Logical.Timer tim0(final t=tSta)
    "Timer for minimum runtime"
  Buildings.Controls.OBC.CDL.Logical.And and2 "Timer for minimum runtime"
  Buildings.Controls.OBC.CDL.Logical.And andUp[nSta]
    "Runtime criterion met AND staging up order"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator rep(
    final nout=nSta)
    "Replicate"
  Buildings.Controls.OBC.CDL.Logical.And andDow[nSta]
    "Runtime criterion met AND staging down order"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator rep1(
    final nout=nSta) "Replicate"
  Modelica.StateGraph.TransitionWithSignal disLag[nSta](
    each final enableTimer=false)
    "Transition disabling lag unit"
  Modelica.StateGraph.TransitionWithSignal disAll[nSta](
    each final enableTimer=false)
    "Transition disabling all units"
  Buildings.Controls.OBC.CDL.Logical.And andNotEna[nSta]
    "Runtime criterion met AND enable signal false"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator rep2(
    final nout=nSta)
    "Replicate"
  Buildings.Controls.OBC.CDL.Logical.Not not1 "True if enable signal false"
  Modelica.Blocks.Sources.IntegerExpression calIdxSta(final y=
        Modelica.Math.BooleanVectors.firstTrueIndex(sta.active))
    "Compute stage index"
  Buildings.Controls.OBC.CDL.Logical.Edge edg
    "Transition to stage 1 at enable time"
  Buildings.Controls.OBC.CDL.Logical.Or or2
    "Transition to stage 1 at enable time or staging up order"
  Modelica.Blocks.Sources.IntegerExpression calPre(final y=pre(idxSta))
    "Compute left limit of stage index"

  Buildings.Controls.OBC.CDL.Logical.And upAndEna "Stage up only if enabled"
  Buildings.Controls.OBC.CDL.Logical.And dowOrDis "Stage down if disabled"
initial equation
  preIdxSta=0;
equation
  for i in 1:(nSta - 1) loop
  connect(enaLag[i].outPort, sta[i+1].inPort[1])
  connect(disLag[i+1].outPort, sta[i].inPort[2])
  end for;
  connect(enaLag[nSta].outPort, sta[nSta].inPort[2])
  connect(disAll.outPort, sta0.inPort[1:nSta])
  connect(sta0.outPort[1], enaLea.inPort)
  connect(enaLea.outPort, sta[1].inPort[1])

  connect(disLag[1].outPort, sta0.inPort[nSta+1])
  connect(sta.outPort[1], disAll.inPort)
  connect(sta.outPort[2], enaLag.inPort)
  connect(sta.outPort[3], disLag.inPort)

  connect(sta.active, tim.u)
  connect(sta0.active, tim0.u)
  connect(tim0.passed, and2.u2)
  connect(and2.y, enaLea.condition)
  connect(rep.y, andUp.u2)
  connect(andUp.y, enaLag.condition)
  connect(tim.passed, andDow.u1)
  connect(rep1.y, andDow.u2)
  connect(tim.passed, andUp.u1)
  connect(andDow.y, disLag.condition)
  connect(u1, not1.u)
  connect(not1.y, rep2.u)
  connect(rep2.y, andNotEna.u1)
  connect(tim.passed, andNotEna.u2)
  connect(andNotEna.y, disAll.condition)

  connect(calIdxSta.y, idxSta)
  connect(u1, edg.u)
  connect(edg.y, or2.u1)
  connect(or2.y, and2.u1)
  connect(calPre.y, preIdxSta)
  connect(u1, upAndEna.u2)
  connect(u1Up, upAndEna.u1)
  connect(upAndEna.y, rep.u)
  connect(dowOrDis.y, rep1.u)
  connect(u1Dow, dowOrDis.u1)
  connect(u1, dowOrDis.u2)
  connect(upAndEna.y, or2.u2)
end StageIndex;


Block that computes plant stage and command signals for chillers and HRC. This block implements the staging logic for the chillers and HRCs.
The units are staged in part based on an efficiency condition
using the operative part load ratio.
The units are also staged based on failsafe conditions using the CHW and HW
supply temperature and differential pressure.

within Buildings.DHC.Plants.Combined.Controls.BaseClasses;
block StagingPlant
  "Block that computes plant stage and command signals for chillers and HRC"

  parameter Integer nChi(final min=1, start=1)
    "Number of units operating at design conditions"
  parameter Modelica.Units.SI.HeatFlowRate QChiWatChi_flow_nominal
    "Cooling design heat flow rate of cooling-only chillers (all units)"
  parameter Integer nChiHea(final min=1, start=1)
    "Number of units operating at design conditions"
  parameter Real PLRStaTra(unit="1") = 0.85
    "Part load ratio triggering stage transition";
  parameter Modelica.Units.SI.HeatFlowRate QChiWatCasCoo_flow_nominal
    "Cooling design heat flow rate of HRC in cascading cooling mode (all units)"
  parameter Modelica.Units.SI.HeatFlowRate QChiWatCasCoo_flow_nominal_approx
    "Cooling design heat flow rate of HRC in cascading cooling mode (all units), approximate for scaling"
  parameter Modelica.Units.SI.HeatFlowRate QHeaWat_flow_nominal
    "Heating design heat flow rate (all units)"
  parameter Modelica.Units.SI.SpecificHeatCapacity cp_default=
    Buildings.Utilities.Psychrometrics.Constants.cpWatLiq
    "Specific heat capacity of the fluid";

  Buildings.Controls.OBC.CDL.Interfaces.RealInput mChiWatPri_flow(
    final unit="kg/s")
    "Primary CHW mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet(
    final unit="K", displayUnit="degC") "CHW supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatPriRet(final unit="K",
      displayUnit="degC") "Primary CHW return temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mHeaWatPri_flow(final unit="kg/s")
    "Primary HW mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatSupSet(
    final unit="K", displayUnit="degC")
    "HW supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatPriRet(final unit="K",
      displayUnit="degC") "Primary HW return temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSup(final unit="K",
      displayUnit="degC") "CHW supply temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWat(final unit="Pa")
    "CHW loop differential pressure"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatSet(final unit="Pa")
    "CHW loop differential pressure setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatSup(final unit="K",
      displayUnit="degC") "HW supply temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHeaWat(final unit="Pa")
    "HW loop differential pressure"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHeaWatSet(final unit="Pa")
    "HW loop differential pressure setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput QCooReq_flow(final unit="W")
    "Plant required cooling capacity (>0)"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Coo
    "Cooling enable signal"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Hea
    "Heating enable signal"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Chi[nChi]
    "Chiller On/Off command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1CooChiHea[nChiHea]
    "HRC cooling mode switchover command: true for cooling, false for heating"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ChiHea[nChiHea]
    "HRC On/Off command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1HeaCooChiHea[nChiHea]
    "HRC cooling mode switchover command: true for cooling, false for heating"

  Buildings.Controls.OBC.CDL.Reals.MovingAverage movAve(delta=300)
    "Moving average"
  Buildings.Controls.OBC.CDL.Reals.Multiply loaChiWat
    "Compute total chiller load (>0)"
  Buildings.Controls.OBC.CDL.Reals.Subtract dTChiWatPos
    "Compute deltaT (>0)"
  Buildings.Controls.OBC.CDL.Reals.Multiply loaHeaWat
    "Compute total chiller load"
  Buildings.Controls.OBC.CDL.Reals.Subtract dTHeaWat "Compute deltaT"
  Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator rep(final nout=
        nChi) "Replicate"
  Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold cmdChi[nChi](final
      t={i for i in 1:nChi})
    "Compute chiller On/Off command from number of units to be commanded On"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter timCp(final k = cp_default)
  "Scale"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter timCp1(final k = cp_default)
   "Scale"
  Buildings.Controls.OBC.CDL.Reals.MovingAverage movAve1(delta=300)
    "Moving average"
  Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator rep5(final nout = nChiHea)
    "Replicate"
  Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold cmdChiHea[nChiHea](
      final t={i for i in 1:nChiHea})
    "Compute chiller On/Off command from number of units to be commanded On"
  Buildings.Controls.OBC.CDL.Integers.Subtract numChiHeaCoo
    "Number of HRC required in direct HR mode"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant numChiHea(final k = nChiHea)
  "Number of HRC"

  Buildings.Controls.OBC.CDL.Integers.Add nChiHeaAndCooUnb
    "Number of HRC required to meet heating and cooling load - Unbounded"
  Buildings.Controls.OBC.CDL.Integers.Subtract numChiCasCoo
    "Number of HRC required in cascading cooling"
  Buildings.DHC.Plants.Combined.Controls.BaseClasses.ModeHeatRecoveryChiller modHeaCoo(final nChiHea=nChiHea)
    "Compute the cascading cooling and direct HR switchover signals"

  Buildings.Controls.OBC.CDL.Integers.Min nChiHeaHeaAndCoo
    "Number of HRC required to meet heating and cooling load - Bounded by number of HRC"

  Buildings.Controls.OBC.CDL.Reals.Subtract errTChiWatSup
    "Compute tracking error"
  Buildings.Controls.OBC.CDL.Reals.Subtract errDpChiWat
    "Compute tracking error"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold cmpErrLim(t=-1, h=1E-4)
    "Check tracking error limit"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold cmpErrLim1(t=1.5E4, h=1E-1)
    "Check tracking error limit"
  Buildings.Controls.OBC.CDL.Logical.Timer timErrExcLim(t=15*60)
    "Timer for error exceeding error limit"
  Buildings.Controls.OBC.CDL.Logical.Timer timErrExcLim1(t=15*60)
    "Timer for error exceeding error limit"
  Buildings.Controls.OBC.CDL.Logical.Or or2 "Failsafe condition to stage up"
  Buildings.Controls.OBC.CDL.Logical.And and2
    "Apply failsafe condition only in stage >= 1"
  Buildings.Controls.OBC.CDL.Logical.And and3
    "Apply failsafe condition only in stage >= 1"
  Buildings.DHC.Plants.Combined.Controls.BaseClasses.StageIndex staCoo(final nSta=nChi + nChiHea, tSta=15*60)
    "Compute cooling stage"
  Modelica.Blocks.Sources.RealExpression capCoo(final y=abs(PLRStaTra*(min(nChi,
        staCoo.preIdxSta)/nChi*QChiWatChi_flow_nominal + max(0, staCoo.preIdxSta
         - nChi)/nChiHea*QChiWatCasCoo_flow_nominal)))
    "Total capacity at current stage (>0) times stage-up PLR limit"
  Buildings.Controls.OBC.CDL.Reals.Greater cmpOPLRLimUp(h=-1E-4*(
        QChiWatChi_flow_nominal + QChiWatCasCoo_flow_nominal_approx)/2)
    "Check OPLR limit"
  Buildings.Controls.OBC.CDL.Logical.Timer timOPLRExcLim(t=15*60)
    "Timer for OPLR exceeding limit"
  Buildings.Controls.OBC.CDL.Logical.Or or1
    "Failsafe condition or efficiency condition to stage up"
  Buildings.Controls.OBC.CDL.Integers.Min numOpeChi
    "Number of operating chillers"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant numChi(final k=nChi)
    "Number of chillers"
  Buildings.Controls.OBC.CDL.Integers.Subtract numOpeCooChiHea
    "Number of HRC required for cooling"
  Modelica.Blocks.Sources.RealExpression capHea(final y=PLRStaTra*staHea.preIdxSta
        /nChiHea*QHeaWat_flow_nominal)
    "Total capacity at current stage times stage-up PLR limit"
  Buildings.Controls.OBC.CDL.Reals.Greater cmpOPLRLimUp1(h=1E-1)
    "Check OPLR limit"
  Buildings.Controls.OBC.CDL.Logical.Timer timOPLRExcLim1(t=15*60)
    "Timer for OPLR exceeding limit"
  Buildings.DHC.Plants.Combined.Controls.BaseClasses.StageIndex staHea(final nSta=nChiHea, tSta=15*60) "Compute heating stage"
  Modelica.Blocks.Sources.RealExpression capHeaLow(final y=PLRStaTra*max(0,
        staHea.preIdxSta - 1)/nChiHea*QHeaWat_flow_nominal)
    "Total capacity at next lower stage times stage-down PLR limit"
  Buildings.Controls.OBC.CDL.Reals.Less cmpOPLRLimDow(h=1E-1)
  "Check OPLR limit"
  Buildings.Controls.OBC.CDL.Logical.Timer timOPLRExcLim2(t=15*60)
    "Timer for OPLR exceeding limit"
  Modelica.Blocks.Sources.RealExpression capCooLow(final y=abs(PLRStaTra*(min(
        nChi, max(0, staCoo.preIdxSta - 1))/nChi*QChiWatChi_flow_nominal + max(
        0, staCoo.preIdxSta - 1 - nChi)/nChiHea*QChiWatCasCoo_flow_nominal)))
    "Total capacity at next lower stage (>0) times stage-down PLR limit"
  Buildings.Controls.OBC.CDL.Reals.Less cmpOPLRLimDow1(h=-1E-4*(
        QChiWatChi_flow_nominal + QChiWatCasCoo_flow_nominal_approx)/2)
    "Check OPLR limit"
  Buildings.Controls.OBC.CDL.Logical.Timer timOPLRExcLim3(t=15*60)
    "Timer for OPLR exceeding limit"
  Buildings.Controls.OBC.CDL.Logical.Not notFail
    "Failsafe conditions are not true"
  Buildings.Controls.OBC.CDL.Logical.And dowAndNotFail
    "No stage up failsafe condition and efficiency condition to stage down"
  Buildings.Controls.OBC.CDL.Reals.Subtract errTChiWatSup1
    "Compute tracking error"
  Buildings.Controls.OBC.CDL.Reals.Subtract errDpHeaWat
    "Compute tracking error"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold   cmpErrLim2(t=+1, h=1E-4)
    "Check tracking error limit"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold cmpErrLim3(t=1.5E4, h=1E-1)
    "Check tracking error limit"
  Buildings.Controls.OBC.CDL.Logical.Timer timErrExcLim2(t=15*60)
    "Timer for error exceeding error limit"
  Buildings.Controls.OBC.CDL.Logical.Timer timErrExcLim3(t=15*60)
    "Timer for error exceeding error limit"
  Buildings.Controls.OBC.CDL.Logical.Or or3 "Failsafe condition to stage up"
  Buildings.Controls.OBC.CDL.Logical.And and1 "Apply failsafe condition only in stage >= 1"
  Buildings.Controls.OBC.CDL.Logical.And and4 "Apply failsafe condition only in stage >= 1"
  Buildings.Controls.OBC.CDL.Logical.Not notFail1
    "Failsafe conditions are not true"
  Buildings.Controls.OBC.CDL.Logical.Or or4
    "Failsafe condition or efficiency condition to stage up"
  Buildings.Controls.OBC.CDL.Logical.And dowAndNotFail1
    "No stage up failsafe condition and efficiency condition to stage down"
  Buildings.DHC.Plants.Combined.Controls.BaseClasses.IntegerArrayHold hol(holdDuration=15*60, nin=4)
    "Minimum plant stage runtime (needed because cooling and heating stage runtimes are handled separately)"

equation
  connect(dTChiWatPos.y, loaChiWat.u2)
  connect(dTHeaWat.y, loaHeaWat.u2)
  connect(THeaWatSupSet, dTHeaWat.u1)
  connect(THeaWatPriRet, dTHeaWat.u2)
  connect(rep.y, cmdChi.u)
  connect(mChiWatPri_flow, timCp.u)
  connect(timCp.y, loaChiWat.u1)
  connect(mHeaWatPri_flow, timCp1.u)
  connect(timCp1.y, loaHeaWat.u1)
  connect(loaChiWat.y, movAve.u)
  connect(loaHeaWat.y, movAve1.u)
  connect(rep5.y, cmdChiHea.u)
  connect(cmdChiHea.y, y1ChiHea)
  connect(modHeaCoo.y1HeaCoo, y1HeaCooChiHea)
  connect(numChiHea.y, nChiHeaHeaAndCoo.u2)
  connect(nChiHeaAndCooUnb.y, nChiHeaHeaAndCoo.u1)
  connect(nChiHeaAndCooUnb.y, numChiHeaCoo.u1)
  connect(nChiHeaHeaAndCoo.y, numChiHeaCoo.u2)
  connect(modHeaCoo.y1Coo, y1CooChiHea)
  connect(numChiHeaCoo.y, numChiCasCoo.u2)
  connect(TChiWatSupSet, errTChiWatSup.u1)
  connect(dpChiWatSet, errDpChiWat.u1)
  connect(errTChiWatSup.y, cmpErrLim.u)
  connect(errDpChiWat.y, cmpErrLim1.u)
  connect(timErrExcLim1.passed, or2.u1)
  connect(timErrExcLim.passed, or2.u2)
  connect(cmpErrLim1.y, and2.u1)
  connect(and2.y, timErrExcLim1.u)
  connect(cmpErrLim.y, and3.u1)
  connect(and3.y, timErrExcLim.u)
  connect(u1Coo, and3.u2)
  connect(u1Coo, and2.u2)
  connect(cmdChi.y, y1Chi)
  connect(u1Coo, staCoo.u1)
  connect(cmpOPLRLimUp.y, timOPLRExcLim.u)
  connect(or2.y, or1.u1)
  connect(or1.y, staCoo.u1Up)
  connect(timOPLRExcLim.passed, or1.u2)
  connect(numChi.y, numOpeChi.u2)
  connect(staCoo.idxSta, numOpeChi.u1)
  connect(staCoo.idxSta, numOpeCooChiHea.u1)
  connect(numOpeChi.y, numOpeCooChiHea.u2)
  connect(numOpeCooChiHea.y, nChiHeaAndCooUnb.u1)
  connect(cmpOPLRLimUp1.y, timOPLRExcLim1.u)
  connect(u1Hea, staHea.u1)
  connect(cmpOPLRLimDow.y, timOPLRExcLim2.u)
  connect(cmpOPLRLimDow1.y, timOPLRExcLim3.u)
  connect(or2.y, notFail.u)
  connect(dowAndNotFail.y, staCoo.u1Dow)
  connect(timOPLRExcLim3.passed, dowAndNotFail.u2)
  connect(notFail.y, dowAndNotFail.u1)
  connect(staHea.idxSta, nChiHeaAndCooUnb.u2)
  connect(numOpeCooChiHea.y, numChiCasCoo.u1)
  connect(movAve.y, cmpOPLRLimUp.u1)
  connect(capCoo.y, cmpOPLRLimUp.u2)
  connect(movAve.y, cmpOPLRLimDow1.u1)
  connect(capCooLow.y, cmpOPLRLimDow1.u2)
  connect(capHea.y, cmpOPLRLimUp1.u2)
  connect(movAve1.y, cmpOPLRLimUp1.u1)
  connect(capHeaLow.y, cmpOPLRLimDow.u2)
  connect(movAve1.y, cmpOPLRLimDow.u1)
  connect(TChiWatSupSet, dTChiWatPos.u2)
  connect(TChiWatPriRet, dTChiWatPos.u1)
  connect(dpHeaWatSet, errDpHeaWat.u1)
  connect(errTChiWatSup1.y, cmpErrLim2.u)
  connect(errDpHeaWat.y, cmpErrLim3.u)
  connect(cmpErrLim3.y,and1. u1)
  connect(and1.y,timErrExcLim3. u)
  connect(cmpErrLim2.y, and4.u1)
  connect(and4.y, timErrExcLim2.u)
  connect(or3.y, notFail1.u)
  connect(THeaWatSupSet, errTChiWatSup1.u1)
  connect(timErrExcLim2.passed, or3.u1)
  connect(timErrExcLim3.passed, or3.u2)
  connect(u1Hea, and4.u2)
  connect(u1Hea, and1.u2)
  connect(timOPLRExcLim1.passed, or4.u1)
  connect(or3.y, or4.u2)
  connect(timOPLRExcLim2.passed, dowAndNotFail1.u1)
  connect(notFail1.y, dowAndNotFail1.u2)
  connect(dowAndNotFail1.y, staHea.u1Dow)
  connect(or4.y, staHea.u1Up)
  connect(numOpeChi.y, hol.u[1])
  connect(numChiCasCoo.y, hol.u[2])
  connect(numChiHeaCoo.y, hol.u[3])
  connect(nChiHeaHeaAndCoo.y, hol.u[4])
  connect(hol.y[1], rep.u)
  connect(hol.y[2], modHeaCoo.nCasCoo)
  connect(hol.y[3], modHeaCoo.nHeaCoo)
  connect(hol.y[4], rep5.u)
  connect(movAve.y, QCooReq_flow)
  connect(dpChiWat, errDpChiWat.u2)
  connect(TChiWatSup, errTChiWatSup.u2)
  connect(THeaWatSup, errTChiWatSup1.u2)
  connect(dpHeaWat, errDpHeaWat.u2)
end StagingPlant;


Pump staging. This block implements the logic for staging the lag pump of
a multiple-pump group.

The first staging criterion is optional and is based on ratFlo,
the ratio of current flow rate to design flow rate.
The lag pump is enabled whenever any of the following is true.

within Buildings.DHC.Plants.Combined.Controls.BaseClasses;
block StagingPump "Pump staging"

  parameter Boolean have_flowCriterion=true
    "Set to true for flow criterion in conjunction with speed criterion"
  parameter Integer nPum(
    final min=1,
    start=1)
    "Number of pumps"
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=1
    "Loop design mass flow rate (all pumps)"
  parameter Real yDow=0.30
    "Low speed limit for staging down";
  parameter Real yUp=0.99
    "High speed limit for staging up";

  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput y1Ena
    "Lead pump Enable signal (e.g. based on isolation valve opening command)"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput m_flow(final unit="kg/s")
    if have_flowCriterion
    "Mass flow rate as measured by the loop flow meter"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput y(final unit="1")
    "Commanded speed"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1[nPum]
    "Start signal (VFD Run or motor starter contact)"

  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold cmp(final t=yUp, h=1e-3)
    "Compare"
  Buildings.Controls.OBC.CDL.Logical.Timer timSpe(t=5*60)
    "True delay"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter ratFlo(
    final k=1/m_flow_nominal) if have_flowCriterion
    "Ratio of current flow rate to design value"
  Buildings.Controls.OBC.CDL.Reals.Greater cmp2(h=1e-3)
    if have_flowCriterion
    "Compare"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addOff(p=-0.03)
    if have_flowCriterion
    "Add offset"
  Buildings.Controls.OBC.CDL.Logical.Timer timFlo(t=10*60)
    if have_flowCriterion
    "Check if true for a given time"
  Buildings.Controls.OBC.CDL.Logical.Or up
    "Check if flow or speed criterion passed for staging up"
  Buildings.Controls.OBC.CDL.Reals.Less cmp3(h=1e-3)
    if have_flowCriterion
    "Compare"
  Buildings.Controls.OBC.CDL.Logical.Timer timFlo1(t=10*60)
    if have_flowCriterion
    "Check if true for a given time"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold  cmp4(final t=yDow, h=1e-3)
    "Compare"
  Buildings.Controls.OBC.CDL.Logical.Timer timSpe1(t=5*60) "True delay"
  Buildings.Controls.OBC.CDL.Logical.Or  dow
    "Check if flow or speed criterion passed for staging down"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter ratOpeDsg(
    final k=1/nPum)
    "Ratio of number of operating pumps to number of operating pumps at design conditions"
  Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold cvtBoo[nPum](
    final t={i for i in 1:nPum})
    "Compute pump Start command from number of pumps to be commanded On"
  Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator rep(
    final nout=nPum) "Replicate"
  Buildings.DHC.Plants.Combined.Controls.BaseClasses.StageIndex staLag(final nSta=max(1, nPum - 1), tSta=30)
    if nPum>1
    "Stage lag pumps (minimum runtime allowing for pump start time)"
  Buildings.Controls.OBC.CDL.Conversions.IntegerToReal cvtInt "Convert"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addOffLowSta(
    final p=-1/nPum) if have_flowCriterion
    "Add offset for lower stage"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger leaEna
    "Return 1 if lead pump enabled"
  Buildings.Controls.OBC.CDL.Integers.Add num "Number of pumps enabled"
  Buildings.Controls.OBC.CDL.Integers.Add numPre "Number of pumps enabled"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant zer(final k=0)
    if nPum==1
    "Constant"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant fal(final k=false)
    if not have_flowCriterion
    "Constant"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput nPumEna
    "Number of pumps that are enabled"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Any
    "Return true if any pump enabled (left limit to avoid direct feedback)"
  Buildings.Controls.OBC.CDL.Integers.GreaterEqualThreshold anyEna(final t=1)
    "Return true if any pump is enabled"
  Buildings.Controls.OBC.CDL.Logical.Pre pre1
    "Left limit of signal avoiding direct feedback"
equation
  connect(y, cmp.u)
  connect(cmp.y, timSpe.u)
  connect(ratFlo.y, cmp2.u1)
  connect(addOff.y, cmp2.u2)
  connect(timFlo.passed, up.u1)
  connect(ratFlo.y, cmp3.u1)
  connect(y, cmp4.u)
  connect(cmp4.y, timSpe1.u)
  connect(timFlo1.passed,dow. u1)
  connect(addOff.u, ratOpeDsg.y)
  connect(rep.y, cvtBoo.u)
  connect(cmp2.y, timFlo.u)
  connect(cmp3.y, timFlo1.u)
  connect(timSpe.passed, up.u2)
  connect(timSpe1.passed,dow. u2)
  connect(y1Ena, staLag.u1)
  connect(cvtInt.y, ratOpeDsg.u)
  connect(cvtBoo.y, y1)
  connect(addOff.y, addOffLowSta.u)
  connect(addOffLowSta.y, cmp3.u2)
  connect(y1Ena, leaEna.u)
  connect(dow.y, staLag.u1Dow)
  connect(num.y, rep.u)
  connect(staLag.idxSta, num.u2)
  connect(leaEna.y, num.u1)
  connect(numPre.y, cvtInt.u)
  connect(leaEna.y, numPre.u1)
  connect(staLag.preIdxSta, numPre.u2)
  connect(zer.y, num.u2)
  connect(zer.y, numPre.u2)
  connect(up.y, staLag.u1Up)
  connect(fal.y, dow.u1)
  connect(fal.y, up.u1)
  connect(num.y, nPumEna)
  connect(anyEna.y, pre1.u)
  connect(pre1.y, y1Any)
  connect(num.y, anyEna.u)
  connect(m_flow, ratFlo.u)
end StagingPump;


Block that determines the tank cycle flag. The tank operating conditions should match the operating limits and selection
conditions of the chillers and HRCs.
The highest temperature (at the top of the tank) should be limited by the
maximum evaporator entering temperature per manufacturer’s recommendations.
The lowest temperature (at the bottom of the tank) should be limited by the
design CHW supply temperature.
This gives the tank maximum ΔT and the actual storage capacity.
However, this value is likely above the maximum ΔT that chillers
and HRCs can achieve across the condenser or evaporator barrel (typically
11 K). Therefore, in order to fully leverage the TES capacity,
two temperature cycles are needed.

within Buildings.DHC.Plants.Combined.Controls.BaseClasses;
block TankCycle "Block that determines the tank cycle flag"

  parameter Modelica.Units.SI.MassFlowRate mConWatHexCoo_flow_nominal
    "Design total CW mass flow rate through condenser barrels (all units)";

  parameter Modelica.Units.SI.Temperature TTanSet[2, 2]
    "Tank temperature setpoints: 2 cycles with 2 setpoints"
  parameter Integer nTTan=0
    "Number of tank temperature points"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput mConWatOutTan_flow(
    final unit="kg/s")
    "Mass flow rate out of lower port of TES tank (>0 when charging)"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TTan[nTTan](
    each final unit="K",
    each displayUnit="degC")
    "TES tank temperature"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerOutput idxCycTan(
    final min=1, final max=2)
    "Index of active tank cycle"

  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold criTem1[nTTan](
    each t=sum(TTanSet[2])/2, each h=1E-4)
    "Temperature criterion for first tank cycle"
  Buildings.Controls.OBC.CDL.Logical.MultiAnd allCriTem1(final nin=nTTan)
    "All temperature criteria met"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold criFlo1(final t=1E-3*
        mConWatHexCoo_flow_nominal, h=1E-3*mConWatHexCoo_flow_nominal/2)
    "Flow criterion for first tank cycle"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold criTem2[nTTan](each t=sum(TTanSet[1])/2, each h=1E-4)
  "Temperature criterion for first tank cycle"
  Buildings.Controls.OBC.CDL.Logical.MultiAnd allCriTem2(final nin=nTTan)
    "All temperature criteria met"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt(final
      integerTrue=1, final integerFalse=2) "Convert"
  Buildings.Controls.OBC.CDL.Logical.Or or2
    "Neither of temperature criterion is true"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt3(final
      integerTrue=2, final integerFalse=0) "Convert"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt4(final
      integerTrue=1, final integerFalse=0) "Convert"
  Buildings.Controls.OBC.CDL.Integers.Max maxInt1 "Set cycle index as maximum"
  Buildings.Controls.OBC.CDL.Logical.And allCri2 "All criteria met"
  Buildings.Controls.OBC.CDL.Logical.And allCri1 "All criteria met"
  Buildings.Controls.OBC.CDL.Integers.Switch idxIni "Index at initial time"
  Buildings.Controls.OBC.CDL.Logical.Timer timAllCri1(t=5*60)
    "All criteria met for given time"
  Buildings.Controls.OBC.CDL.Logical.Timer timAllCri2(t=5*60)
    "All criteria met for given time"
  Buildings.Controls.OBC.CDL.Integers.Switch
                                           intSwi "Switch index"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant idx1(final k=1) "Index"
  Buildings.Controls.OBC.CDL.Integers.Switch
                                           intSwi1 "Switch index"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant idx2(final k=2) "Index"
  Modelica.Blocks.Sources.IntegerExpression preIdxCycTan(y=pre(idxCycTan))
    "Previous index value"
  Buildings.Controls.OBC.CDL.Logical.Not criFlo2
    "Flow criterion for second tank cycle"
  Buildings.DHC.Plants.Combined.Controls.BaseClasses.IntegerArrayHold hol(holdDuration=30*60, nin=1) "Hold for minimum runtime"
initial equation
  pre(idxCycTan)=idxIni.y;
equation
  connect(criTem1.y, allCriTem1.u)
  connect(TTan, criTem2.u)
  connect(TTan, criTem1.u)
  connect(criTem2.y, allCriTem2.u)
  connect(allCriTem2.y, booToInt3.u)
  connect(allCriTem1.y, booToInt4.u)
  connect(allCriTem1.y, allCri1.u1)
  connect(allCriTem2.y, allCri2.u1)
  connect(maxInt1.u2, booToInt3.y)
  connect(booToInt4.y, maxInt1.u1)
  connect(allCriTem1.y, or2.u1)
  connect(allCriTem2.y, or2.u2)
  connect(or2.y, idxIni.u2)
  connect(maxInt1.y, idxIni.u1)
  connect(criFlo1.y, booToInt.u)
  connect(booToInt.y, idxIni.u3)
  connect(mConWatOutTan_flow, criFlo1.u)
  connect(allCri1.y, timAllCri1.u)
  connect(allCri2.y, timAllCri2.u)
  connect(timAllCri1.passed, intSwi.u2)
  connect(idx1.y, intSwi.u1)
  connect(timAllCri2.passed, intSwi1.u2)
  connect(idx2.y, intSwi1.u1)
  connect(intSwi1.y, intSwi.u3)
  connect(preIdxCycTan.y, intSwi1.u3)
  connect(criFlo1.y, criFlo2.u)
  connect(hol.y[1], idxCycTan)
  connect(criFlo1.y, allCri1.u2)
  connect(criFlo2.y, allCri2.u2)
  connect(intSwi.y, hol.u[1])
end TankCycle;


Controller for chiller and HRC condenser and evaporator valves. This block implements the control logic for the chiller isolation valves,
the HRC isolation and switchover valves, the CHW and HW minimum flow
bypass valves, the HRC evaporator CW mixing valve, and the
CW chiller bypass valve.
It also computes the lead pump Enable signal for the CHW, HW, CWC and CWE
pump groups.

within Buildings.DHC.Plants.Combined.Controls.BaseClasses;
block ValveCondenserEvaporator
  "Controller for chiller and HRC condenser and evaporator valves"

  parameter Integer nChi(final min=1, start=1)
    "Number of units operating at design conditions"
  parameter Integer nChiHea(final min=1, start=1)
    "Number of units operating at design conditions"
  parameter Modelica.Units.SI.MassFlowRate mChiWatChi_flow_nominal
    "Chiller CHW design mass flow rate (value will be used for each unit)"
  parameter Modelica.Units.SI.MassFlowRate mChiWatChi_flow_min
    "Chiller CHW minimum mass flow rate (value will be used for each unit)"
  parameter Modelica.Units.SI.MassFlowRate mConWatChi_flow_nominal
    "Chiller CW design mass flow rate (value will be used for each unit)"
  parameter Modelica.Units.SI.PressureDifference dpEvaChi_nominal(displayUnit="Pa")
    "Chiller evaporator design pressure drop (value will be used for each unit)"
  parameter Modelica.Units.SI.PressureDifference dpValEvaChi_nominal(
      displayUnit="Pa")
    "Chiller evaporator isolation valve design pressure drop (value will be used for each unit)"
  parameter Modelica.Units.SI.MassFlowRate mChiWatChiHea_flow_nominal
    "HRC CHW design mass flow rate (value will be used for each unit)"
  parameter Modelica.Units.SI.MassFlowRate mChiWatChiHea_flow_min
    "HRC CHW minimum mass flow rate (value will be used for each unit)"
  parameter Modelica.Units.SI.MassFlowRate mConWatChiHea_flow_nominal
    "HRC CW design mass flow rate (value will be used for each unit)"
  parameter Modelica.Units.SI.MassFlowRate mHeaWatChiHea_flow_min
    "Chiller HW minimum mass flow rate (value will be used for each unit)"
  parameter Modelica.Units.SI.PressureDifference dpEvaChiHea_nominal(
      displayUnit="Pa")
    "Design chiller evaporator  pressure drop (value will be used for each unit)"
  parameter Modelica.Units.SI.PressureDifference dpValEvaChiHea_nominal(
      displayUnit="Pa")
    "HRC evaporator isolation valve design pressure drop (value will be used for each unit)"
  parameter Modelica.Units.SI.Temperature TTanSet[2, 2]
    "Tank temperature setpoints: 2 cycles with 2 setpoints"
  parameter Real k(min=0)=0.01
    "Gain of controller"
  parameter Modelica.Units.SI.Time Ti=60
    "Time constant of integrator block"
  parameter Real yMin=0.1
    "Lower limit of valve opening when control loop enabled"
  parameter Real y_reset=1
    "Value to which the controller output is reset if the boolean trigger has a rising edge"
  parameter Real y_neutral=0
    "Value to which the controller output is reset when the controller is disabled"
  parameter Real yBalEvaChi = if dpEvaChiHea_nominal + dpValEvaChiHea_nominal - dpEvaChi_nominal <= 0
    then 1 else (dpValEvaChi_nominal / (dpEvaChiHea_nominal + dpValEvaChiHea_nominal - dpEvaChi_nominal))^0.5
    "Chiller evaporator isolation valve opening for flow balancing with HRC";
  parameter Real yBalEvaChiHea = if dpEvaChi_nominal + dpValEvaChi_nominal - dpEvaChiHea_nominal <= 0
    then 1 else (dpValEvaChiHea_nominal / (dpEvaChi_nominal + dpValEvaChi_nominal - dpEvaChiHea_nominal))^0.5
    "HRC evaporator isolation valve opening for flow balancing with chiller";

  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput idxCycTan(final min=1,
      final max=2)
    "Index of active tank cycle"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput mode(final min=Buildings.DHC.Plants.Combined.Controls.ModeCondenserLoop.tankCharge,
      final max=Buildings.DHC.Plants.Combined.Controls.ModeCondenserLoop.heatRejection)
    "Condenser loop operating mode"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Chi[nChi]
    "Cooling-only chiller On/Off command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1ChiHea[nChiHea]
    "HRC On/Off command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1CooChiHea[nChiHea]
    "HRC cooling mode switchover command: true for cooling, false for heating"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1HeaCooChiHea[nChiHea]
    "HRC direct heat recovery switchover command: true for direct HR, false for cascading"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TEvaLvgChiHea[nChiHea](each final
            unit="K", each displayUnit="degC")
    "HRC evaporator barrel leaving temperature"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput mEvaChiSet_flow(final
      unit="kg/s") "Chiller evaporator flow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mEvaChiHeaSet_flow(final
            unit="kg/s") "HRC evaporator flow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mEvaChi_flow[nChi](
    each final unit="kg/s")
    "Chiller evaporator mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mConChi_flow[nChi](
    each final unit="kg/s")
    "Chiller condenser mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mEvaChiHea_flow[nChiHea](
    each final unit="kg/s")
    "HRC evaporator mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatEvaEnt(final unit="K",
      displayUnit="degC") "HRC evaporator entering CW temperature "
  Buildings.Controls.OBC.CDL.Interfaces.RealInput mConChiHea_flow[nChiHea](
    each final unit="kg/s")
    "HRC condenser mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConEntChiHeaSet(final unit="K",
      displayUnit="degC") "HRC condenser entering temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConEntChiHea[nChiHea](each final
      unit="K", each displayUnit="degC") "HRC condenser entering temperature"

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConLvgChiHea[nChiHea](each final
            unit="K", each displayUnit="degC")
    "HRC condenser barrel leaving temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConLvgChi[nChi](each final
      unit="K", each displayUnit="degC")
    "Chiller condenser barrel leaving temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TConWatConRet(final unit=
       "K", displayUnit="degC") "CWC return temperature"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumChiWat
    "Enable signal for lead CHW pump"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumHeaWat
    "Enable signal for lead HW pump"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumConWatCon
    "Enable signal for lead CW pump serving evaporator loop"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumConWatEva
    "Enable signal for lead CW pump serving evaporator loop"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValEvaChi[nChi]
    "Cooling-only chiller evaporator isolation valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValConChi[nChi](each final
      unit="1")
    "Cooling-only chiller condenser isolation valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValEvaChiHea[nChiHea](each final
            unit="1") "HRC evaporator isolation valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValConChiHea[nChiHea](each final
            unit="1") "HRC condenser isolation valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValEvaSwiChiHea[nChiHea](
      each final unit="1") "HRC evaporator switchover valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValConSwiChiHea[nChiHea](
      each final unit="1") "HRC condenser switchover valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValConWatEvaMix
    "HRC evaporator CW mixing valve commanded position"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValChiWatMinByp(final unit=
        "1") "CHW minimum flow bypass valve control signal"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValHeaWatMinByp(final unit=
        "1") "HW minimum flow bypass valve control signal"
  ETS.Combined.Controls.PIDWithEnable valEvaChi[nChi](
    each k=k,
    each Ti=Ti,
    each final yMin=yMin,
    each final yMax=1,
    each final reverseActing=true,
    each final y_reset=y_reset,
    each final y_neutral=y_neutral)
    "Chiller evaporator isolation valve control when HRC in direct HR"
  ETS.Combined.Controls.PIDWithEnable valConChi[nChi](
    each k=k,
    each Ti=Ti,
    each final yMin=yMin,
    each final yMax=1,
    each final reverseActing=true,
    each final y_reset=y_reset,
    each final y_neutral=y_neutral) "Chiller condenser isolation valve control"
  ETS.Combined.Controls.PIDWithEnable valEvaChiHea[nChiHea](
    each k=4*k,
    each Ti=Ti/3,
    each final yMin=yMin,
    each final yMax=1,
    each final reverseActing=true,
    each final y_reset=y_reset,
    each final y_neutral=y_neutral) "HRC evaporator isolation valve control"
  ETS.Combined.Controls.PIDWithEnable valConChiHea[nChiHea](
    each k=k,
    each Ti=Ti,
    each final yMin=yMin,
    each final yMax=1,
    each final reverseActing=true,
    each final y_reset=y_reset,
    each final y_neutral=y_neutral)
    "HRC condenser isolation valve control"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal yValConSwi[nChiHea]
    "HRC condenser switchover valve commanded position"
  Buildings.Controls.OBC.CDL.Logical.Not hea[nChiHea] "Return true if heating"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt[nChiHea](
    each final integerTrue=1,
    each final integerFalse=0) "Convert"
  Buildings.Controls.OBC.CDL.Integers.MultiSum numHeaAndOn(nin=nChiHea)
    "Number of HRC connected to HW loop and On"
  Buildings.Controls.OBC.CDL.Integers.Less intLes[nChiHea]
    "Return true if switchover valve to be open for heating operation"
  Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator rep(
    final nout=nChiHea)
    "Replicate"
  Buildings.Controls.OBC.CDL.Logical.Or heaOrCooCon[nChiHea]
    "Return true if switchover valve to be open for heating or cooling operation"
  Buildings.Controls.OBC.CDL.Logical.And heaAndOn[nChiHea]
    "Return true if heating AND On"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant idx[nChiHea](final k={i
        for i in 1:nChiHea}) "HRC index"
  Buildings.Controls.OBC.CDL.Logical.Or cooOrDir[nChiHea]
    "Return true if cooling OR direct HR"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal yValEvaSwi[nChiHea]
    "HRC evaporator switchover valve commanded position"
  Buildings.Controls.OBC.CDL.Logical.Not heaAndCas[nChiHea]
    "Return true if cascading heating"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger booToInt1[nChiHea]
    "Convert"
  Buildings.Controls.OBC.CDL.Integers.MultiSum numHeaAndCasAndOn(nin=nChiHea)
    "Number of HRC in cascading heating AND On"
  Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator rep1(final nout=
        nChiHea) "Replicate"
  Buildings.Controls.OBC.CDL.Integers.Less intLes1[nChiHea]
    "Return true if switchover valve to be open for heating operation"
  Buildings.Controls.OBC.CDL.Logical.Or heaOrCooEva[nChiHea]
    "Return true if switchover valve to be open for heating or cooling operation"
  Buildings.Controls.OBC.CDL.Logical.And cooOrDirAndOn[nChiHea]
    "Return true if (cooling OR direct HR) AND On"
  Buildings.Controls.OBC.CDL.Logical.And heaAndCasAndOn[nChiHea]
    "Return true if cascading heating AND On"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold isOpe[nChiHea](each t=0.1,
      each h=5E-2) "Check if valve open"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold isOpe1[nChiHea](each t=
       0.1, each h=5E-2) "Check if valve open"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold isOpe2[nChi](each t=0.1,
      each h=5E-2) "Check if valve open"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold isOpe3[nChi](each t=0.1,
      each h=5E-2) "Check if valve open"
  Buildings.Controls.OBC.CDL.Logical.And cooOrDirAndOnAndOpe[nChiHea]
    "Return true if HRC (cooling OR direct HR) AND On AND isolation valve open"
  Buildings.Controls.OBC.CDL.Logical.And onAndOpe[nChi]
    "Return true if On AND isolation valve open"
  Buildings.Controls.OBC.CDL.Logical.And onAndOpe1[nChi]
    "Return true if On AND isolation valve open"
  Buildings.Controls.OBC.CDL.Logical.MultiOr enaPumChiWat(nin=nChi+nChiHea)
    "Enable signal for lead CHW pump"
  Buildings.Controls.OBC.CDL.Logical.MultiOr enaPumConWatCon(nin=nChi+nChiHea+1)
    "Enable signal for lead CW pump serving condenser loop"
  Buildings.Controls.OBC.CDL.Logical.And cooAndOpe[nChiHea]
    "Return true if cooling (necessarily cascading) AND isolation valve open"
  Buildings.Controls.OBC.CDL.Logical.MultiOr enaPumHeaWat(nin=nChiHea)
    "Enable signal for lead HW pump"
  Buildings.Controls.OBC.CDL.Logical.MultiOr enaPumConWatEva(nin=nChiHea)
    "Enable signal for lead CW pump serving evaporator loop"
  Buildings.Controls.OBC.CDL.Logical.And heaAndOnAndOpe[nChiHea]
    "Return true if heating AND On AND isolation valve open"
  Buildings.Controls.OBC.CDL.Logical.And heaAndCasAndOnAndOpe[nChiHea]
    "Return true if cascading heating AND On AND isolation valve open"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep2(final nout=nChi)
    "Replicate"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep3(final nout=
        nChiHea) "Replicate"
  Buildings.Controls.OBC.CDL.Logical.And dirHeaCooAndOn[nChiHea]
    "Return true if direct HR AND On"
  Buildings.Controls.OBC.CDL.Logical.MultiOr anyDirHeaCooAndOn(nin=nChiHea)
    "Return true if any HRC in direct HR AND On"
  ETS.Combined.Controls.PIDWithEnable valConSwi(
    u_s(unit="K", displayUnit="degC"),
    u_m(unit="K", displayUnit="degC"),
    k=k,
    Ti=Ti,
    final yMin=0,
    final yMax=1,
    final reverseActing=false,
    final y_reset=0,
    final y_neutral=0)
    "Condenser switchover valve control"
  Modelica.Blocks.Sources.IntegerExpression idxHig(final y=max({if
        dirHeaCooAndOn[i].y then i else 1 for i in 1:nChiHea}))
    "Highest index of HRC in direct HR (defaulted to 1 if all false)"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep4(final nout=
        nChiHea) "Replicate"
  Buildings.Controls.OBC.CDL.Integers.Equal equIdx[nChiHea]
    "Return true if index equals highest index of HRC in direct HR"
  Modelica.Blocks.Sources.IntegerExpression idxChiHea[nChiHea](final y={i for i in
            1:nChiHea}) "HRC index"
  Buildings.Controls.OBC.CDL.Reals.Switch selCtl[nChiHea]
    "Select control signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer[nChiHea](each final
            k=0) "Constant"
  Buildings.Controls.OBC.CDL.Reals.Max max1[nChiHea]
    "Take into account entering CW temperature control in direct HR mode"
  Buildings.Controls.OBC.CDL.Routing.RealExtractor extT(final nin=nChiHea)
    "Extract value at given index"
  Buildings.Controls.OBC.CDL.Routing.IntegerScalarReplicator rep5(final nout=
        nChiHea) "Replicate"
  ETS.Combined.Controls.PIDWithEnable ctlTConWatEvaLvg[nChiHea](
    u_s(each final unit="K", each displayUnit="degC"),
    u_m(each final unit="K", each displayUnit="degC"),
    each final k=k/2,
    each Ti=Ti,
    each final yMin=0,
    each final yMax=1,
    each final reverseActing=true,
    each final y_reset=0.75,
    each final y_neutral=0.75) "HRC evaporator leaving temperature control"
  Buildings.Controls.OBC.CDL.Routing.RealExtractor TConWatEvaLvgSet(final nin=2)
    "Extract value at given index"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TConWatEvaLvgSetCst[2](
    final k=TTanSet[:, 1])
    "HRC evaporator leaving CW temperature setpoint"

  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep6(final nout=
        nChiHea) "Replicate"
  Buildings.Controls.OBC.CDL.Reals.Line valConWatEvaMix[nChiHea]
    "Mixing valve opening reset: 1 means no bypass flow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant xVal[nChiHea,2](final
      k=fill({0,0.5}, nChiHea)) "x-value for mixing valve opening reset"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yVal[nChiHea,2](final k=
        fill({0,1}, nChiHea))
    "y-value for mixing valve opening reset: 1 means no bypass flow"
  Buildings.Controls.OBC.CDL.Reals.Line floEva[nChiHea]
    "HRC evaporator flow reset when On AND cascading heating"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant xFlo[nChiHea,2](final
      k=fill({0.5,1}, nChiHea)) "x-value for evaporator flow reset"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yFlo[nChiHea,2](final
      k=fill({mChiWatChiHea_flow_min,mChiWatChiHea_flow_nominal}, nChiHea))
    "y-value for evaporator flow reset"
  Buildings.Controls.OBC.CDL.Reals.Switch selFloSet[nChiHea]
    "Select HRC evaporator flow setpoint based on operating mode"
  ETS.Combined.Controls.PIDWithEnable ctlTConWatEvaEnt(
    u_s(final unit="K", displayUnit="degC"),
    u_m(final unit="K", displayUnit="degC"),
    k=k,
    Ti=Ti,
    final yMin=0,
    final yMax=1,
    final reverseActing=true,
    final y_reset=1,
    final y_neutral=1)
    "HRC evaporator entering temperature control: 1 means no bypass flow"
  Buildings.Controls.OBC.CDL.Logical.MultiOr anyHeaAndCasAndOn(nin=nChiHea)
    "Return true if ANY HRC cascading heating AND On"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TConWatEvaEntSet(final k=
        max(TTanSet))      "HRC evaporator entering CW temperature setpoint"
  Buildings.Controls.OBC.CDL.Reals.MultiMin mulMin(nin=nChiHea+1)
    "Combine outputs from evaporator entering and leaving temperature control"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TConWatConRetSetCst[2](final
      k=TTanSet[:, 2]) "CW condenser loop return temperature setpoint"
  Buildings.Controls.OBC.CDL.Routing.RealExtractor TConWatConRetSet(final nin=2)
    "Extract value at given index"
  ETS.Combined.Controls.PIDWithEnable ctlTConWatConRet(
    u_s(final unit="K", displayUnit="degC"),
    u_m(final unit="K", displayUnit="degC"),
    k=k,
    Ti=Ti,
    final yMin=0,
    final yMax=1,
    final reverseActing=false,
    final y_reset=0.2,
    final y_neutral=0.0)
    "Condenser loop CW return temperature control"
  Buildings.Controls.OBC.CDL.Integers.Equal isChaAss
    "Check if charge assist mode is active"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant chaAss(final k=Buildings.DHC.Plants.Combined.Controls.ModeCondenserLoop.chargeAssist)
    "Charge assist mode index"
  Buildings.Controls.OBC.CDL.Reals.Line floCon[nChi + nChiHea]
    "Condenser flow reset (normalized output)"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant xFloCon[nChi + nChiHea,
    2](final k=fill({0,1}, nChi + nChiHea)) "x-value for flow reset"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yFloCon[nChi + nChiHea,
    2](final k=fill({0.1,1}, nChi + nChiHea))
    "y-value for condenser flow reset"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter scaFloConChi[nChi](
      each final k=mConWatChi_flow_nominal) "Scale flow reset signal"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter scaFloConChiHea[nChiHea](
      each final k=mConWatChiHea_flow_nominal) "Scale flow reset signal"
  ETS.Combined.Controls.PIDWithEnable ctlTConLvgChi[nChi +
    nChiHea](
    u_s(each final unit="K", each displayUnit="degC"),
    u_m(each final unit="K", each displayUnit="degC"),
    each k=k,
    each Ti=Ti,
    each final yMin=0,
    each final yMax=1,
    each final reverseActing=false,
    each final y_reset=0.5,
    each final y_neutral=0) "Condenser leaving temperature control"

  Buildings.Controls.OBC.CDL.Integers.Sources.Constant tanCha(final k=Buildings.DHC.Plants.Combined.Controls.ModeCondenserLoop.tankCharge)
    "Tank charge/discharge mode index"
  Buildings.Controls.OBC.CDL.Integers.Equal isTanCha
    "Check if tank charge/discharge mode is active"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator
                                                          rep9(final nout=nChi +
        nChiHea) "Replicate"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep10(final nout=nChi +
        nChiHea) "Replicate"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator rep11(final nout=nChi +
        nChiHea) "Replicate"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one[nChi + nChiHea](
      each final k=1) "Constant"
  Buildings.Controls.OBC.CDL.Reals.Switch swiFloSet[nChi + nChiHea]
    "Switch condenser flow setpoint based on condenser loop operating mode"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator
                                                          rep12(final nout=nChi +
        nChiHea) "Replicate"
  Buildings.Controls.OBC.CDL.Reals.Switch swiFloSet1[nChi + nChiHea]
    "Switch condenser flow setpoint based on condenser loop operating mode"
  ETS.Combined.Controls.PIDWithEnable valChiWatMinByp[nChi +
    nChiHea](
    each k=0.01,
    each Ti=Ti,
    each final yMin=0,
    each final yMax=1,
    each final reverseActing=true,
    each final y_reset=0,
    each final y_neutral=0) "CHW minimum flow bypass valve control"
  ETS.Combined.Controls.PIDWithEnable valHeaWatMinByp[nChiHea](
    each k=0.01,
    each Ti=Ti,
    each final yMin=0,
    each final yMax=1,
    each final reverseActing=true,
    each final y_reset=0,
    each final y_neutral=0) "HW minimum flow bypass valve control"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant floChiWatMin[nChi +
    nChiHea](final k=1.1*cat(
        1,
        fill(mChiWatChi_flow_min, nChi),
        fill(mChiWatChiHea_flow_min, nChiHea))) "Minimum flow setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant floHeaWatMin[nChiHea](final k=
        1.1*fill(mHeaWatChiHea_flow_min, nChiHea))   "Minimum flow setpoint"
  Buildings.Controls.OBC.CDL.Reals.MultiMax max2(nin=nChi + nChiHea)
    "Maximum control signal"
  Buildings.Controls.OBC.CDL.Reals.MultiMax max3(nin=nChiHea)
    "Maximum control signal"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator
                                                          rep7(final nout=nChi)
    "Replicate"
  Buildings.Controls.OBC.CDL.Reals.Switch swi[nChi]
    "Condition to enable evaporator flow control loop"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1[nChi](final k=
        fill(0, nChi)) "Constant"
  Buildings.Controls.OBC.CDL.Logical.Not noHeaAndCooAndOn
    "Return true if NO HRC in direct HR AND On"
  Buildings.Controls.OBC.CDL.Logical.MultiOr anyCooAndOn(nin=nChiHea)
    "Return true if ANY HRC in cascading cooling AND On"
  Buildings.Controls.OBC.CDL.Logical.And and2
    "Condition to switch to fixed valve opening (balancing)"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator
                                                          rep8(final nout=nChi)
    "Replicate"
  Buildings.Controls.OBC.CDL.Reals.Switch swi1[nChi]
    "Condition to enable evaporator flow control loop"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yBalChi[nChi](final k=
        fill(yBalEvaChi, nChi)) "Constant"
  Buildings.Controls.OBC.CDL.Logical.Not fulOpe[nChi]
    "Condition to switch to fixed full opening"
  Buildings.Controls.OBC.CDL.Reals.Switch swi2[nChi]
    "Condition to enable evaporator flow control loop"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one1[nChi](final k=
        fill(1, nChi)) "Constant"
  Buildings.Controls.OBC.CDL.Logical.And cooAndOn[nChiHea]
    "Return true if HRC in cascading cooling AND On"
  Buildings.Controls.OBC.CDL.Reals.Switch selValPos[nChiHea]
    "Select HRC evaporator isolation valve command signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yBalChiHea[nChiHea](
      final k=fill(yBalEvaChiHea, nChiHea)) "Constant"
  Buildings.Controls.OBC.CDL.Logical.MultiOr anyCooOrDirAndOn(nin=nChiHea)
    "Return true if any HRC in (cooling OR direct HR) AND On"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator rep13(final nout=nChi)
    "Replicate"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nChiHea]
    "Convert"
  Buildings.Controls.OBC.CDL.Reals.Max max4[nChiHea] "Convert"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValConWatByp(final unit="1")
    "CW chiller bypass valve control signal"
  Buildings.Controls.OBC.CDL.Logical.Not isCloConChi[nChi]
    "Check if valve closed"
  Buildings.Controls.OBC.CDL.Logical.MultiAnd allCloAndChaAndEna(nin=nChi+2)
    "Check if all valves closed AND Charge Assist mode is active"
  Buildings.Controls.OBC.CDL.Reals.Switch enaCtlValConWatByp
    "Enable CW bypass valve control"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer2(final k=0)
    "Constant"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold isOpe4(t=0.1, h=5E-2)
                   "Check if valve open"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1CooOrHea
    "Plant Enable signal: either cooling or heating is enabled"
equation
  connect(u1Chi, valConChi.uEna)
  connect(valConChi.y, yValConChi)
  connect(rep.y,intLes. u2)
  connect(intLes.y, heaOrCooCon.u2)
  connect(heaOrCooCon.y, yValConSwi.u)
  connect(numHeaAndOn.y, rep.u)
  connect(u1CooChiHea, hea.u)
  connect(u1ChiHea, heaAndOn.u1)
  connect(hea.y, heaAndOn.u2)
  connect(heaAndOn.y, booToInt.u)
  connect(idx.y, intLes.u1)
  connect(cooOrDir.y,heaAndCas. u)
  connect(booToInt1.y, numHeaAndCasAndOn.u)
  connect(numHeaAndCasAndOn.y, rep1.u)
  connect(rep1.y,intLes1. u2)
  connect(intLes1.y, heaOrCooEva.u2)
  connect(heaOrCooEva.y, yValEvaSwi.u)
  connect(u1CooChiHea, cooOrDir.u1)
  connect(u1HeaCooChiHea, cooOrDir.u2)
  connect(cooOrDir.y, cooOrDirAndOn.u2)
  connect(u1ChiHea, cooOrDirAndOn.u1)
  connect(heaAndCas.y, heaAndCasAndOn.u2)
  connect(u1ChiHea, heaAndCasAndOn.u1)
  connect(heaAndCasAndOn.y, booToInt1.u)
  connect(booToInt.y, numHeaAndOn.u)
  connect(idx.y, intLes1.u1)
  connect(cooOrDirAndOn.y, heaOrCooEva.u1)
  connect(yValEvaChi, isOpe2.u)
  connect(yValConChi, isOpe3.u)
  connect(yValEvaChiHea, isOpe.u)
  connect(yValConChiHea, isOpe1.u)
  connect(isOpe.y, cooOrDirAndOnAndOpe.u1)
  connect(cooOrDirAndOn.y, cooOrDirAndOnAndOpe.u2)
  connect(isOpe2.y, onAndOpe.u2)
  connect(u1Chi, onAndOpe.u1)
  connect(isOpe3.y, onAndOpe1.u2)
  connect(u1Chi, onAndOpe1.u1)
  connect(onAndOpe[1:nChi].y, enaPumChiWat.u[1:nChi])
  connect(cooOrDirAndOnAndOpe[1:nChiHea].y, enaPumChiWat.u[nChi+1:nChi+nChiHea])
  connect(onAndOpe1[1:nChi].y, enaPumConWatCon.u[1:nChi])
  connect(u1CooChiHea, cooAndOpe.u1)
  connect(isOpe1.y, cooAndOpe.u2)
  connect(cooAndOpe[1:nChiHea].y, enaPumConWatCon.u[nChi+1:nChi+nChiHea])
  connect(heaAndOn.y, heaAndOnAndOpe.u1)
  connect(isOpe1.y, heaAndOnAndOpe.u2)
  connect(heaAndOnAndOpe.y, enaPumHeaWat.u)
  connect(heaAndCasAndOn.y, heaAndCasAndOnAndOpe.u1)
  connect(isOpe.y, heaAndCasAndOnAndOpe.u2)
  connect(heaAndCasAndOnAndOpe.y, enaPumConWatEva.u)
  connect(enaPumChiWat.y, y1PumChiWat)
  connect(enaPumConWatCon.y, y1PumConWatCon)
  connect(enaPumHeaWat.y, y1PumHeaWat)
  connect(rep3.u, mEvaChiHeaSet_flow)
  connect(yValEvaSwi.y, yValEvaSwiChiHea)
  connect(enaPumConWatEva.y, y1PumConWatEva)
  connect(u1ChiHea, dirHeaCooAndOn.u1)
  connect(u1HeaCooChiHea, dirHeaCooAndOn.u2)
  connect(dirHeaCooAndOn.y, anyDirHeaCooAndOn.u)
  connect(TConEntChiHeaSet, valConSwi.u_s)
  connect(anyDirHeaCooAndOn.y, valConSwi.uEna)
  connect(valConSwi.y, rep4.u)
  connect(equIdx.y, selCtl.u2)
  connect(rep4.y, selCtl.u1)
  connect(zer.y, selCtl.u3)
  connect(yValConSwi.y, max1.u1)
  connect(max1.y, yValConSwiChiHea)
  connect(selCtl.y, max1.u2)
  connect(TConEntChiHea, extT.u)
  connect(idxHig.y, extT.index)
  connect(extT.y, valConSwi.u_m)
  connect(idxHig.y, rep5.u)
  connect(idxChiHea.y, equIdx.u2)
  connect(rep5.y, equIdx.u1)
  connect(heaAndCasAndOn.y, ctlTConWatEvaLvg.uEna)
  connect(TEvaLvgChiHea, ctlTConWatEvaLvg.u_m)
  connect(TConWatEvaLvgSetCst.y, TConWatEvaLvgSet.u)
  connect(idxCycTan, TConWatEvaLvgSet.index)
  connect(rep6.y, ctlTConWatEvaLvg.u_s)
  connect(TConWatEvaLvgSet.y, rep6.u)
  connect(yVal[:, 2].y, valConWatEvaMix.f2)
  connect(yVal[:, 1].y, valConWatEvaMix.f1)
  connect(xVal[:, 1].y, valConWatEvaMix.x1)
  connect(xVal[:, 2].y, valConWatEvaMix.x2)
  connect(yFlo[:, 2].y, floEva.f2)
  connect(yFlo[:, 1].y, floEva.f1)
  connect(xFlo[:, 1].y, floEva.x1)
  connect(xFlo[:, 2].y, floEva.x2)
  connect(heaAndCasAndOn.y, selFloSet.u2)
  connect(rep3.y, selFloSet.u3)
  connect(ctlTConWatEvaLvg.y, valConWatEvaMix.u)
  connect(ctlTConWatEvaLvg.y, floEva.u)
  connect(selFloSet.y, valEvaChiHea.u_s)
  connect(floEva.y, selFloSet.u1)
  connect(TConWatEvaEnt, ctlTConWatEvaEnt.u_m)
  connect(anyHeaAndCasAndOn.y, ctlTConWatEvaEnt.uEna)
  connect(heaAndCasAndOn.y, anyHeaAndCasAndOn.u)
  connect(TConWatEvaEntSet.y, ctlTConWatEvaEnt.u_s)
  connect(ctlTConWatEvaEnt.y, mulMin.u[nChiHea+1])
  connect(valConWatEvaMix.y, mulMin.u[1:nChiHea])
  connect(mulMin.y, yValConWatEvaMix)
  connect(TConWatConRetSetCst.y, TConWatConRetSet.u)
  connect(idxCycTan, TConWatConRetSet.index)
  connect(mode, isChaAss.u1)
  connect(chaAss.y, isChaAss.u2)
  connect(isChaAss.y, ctlTConWatConRet.uEna)
  connect(TConWatConRetSet.y, ctlTConWatConRet.u_s)
  connect(TConWatConRet, ctlTConWatConRet.u_m)
  connect(xFloCon[:, 1].y, floCon.x1)
  connect(xFloCon[:, 2].y, floCon.x2)
  connect(mode, isTanCha.u2)
  connect(tanCha.y, isTanCha.u1)
  connect(TConLvgChi, ctlTConLvgChi[1:nChi].u_m)
  connect(TConLvgChiHea, ctlTConLvgChi[nChi + 1:nChi + nChiHea].u_m)
  connect(isTanCha.y, rep9.u)
  connect(rep9.y, ctlTConLvgChi.uEna)
  connect(rep10.y, ctlTConLvgChi.u_s)
  connect(ctlTConWatConRet.y, rep11.u)
  connect(TConWatConRetSet.y, rep10.u)
  connect(rep12.y, swiFloSet.u2)
  connect(isChaAss.y, rep12.u)
  connect(rep11.y, swiFloSet.u1)
  connect(rep9.y, swiFloSet1.u2)
  connect(ctlTConLvgChi.y, swiFloSet1.u1)
  connect(one.y, swiFloSet1.u3)
  connect(swiFloSet1.y, swiFloSet.u3)
  connect(swiFloSet.y, floCon.u)
  connect(yFloCon[:, 1].y, floCon.f1)
  connect(yFloCon[:, 2].y, floCon.f2)
  connect(scaFloConChi.y, valConChi.u_s)
  connect(scaFloConChiHea.y, valConChiHea.u_s)
  connect(floCon[nChi + 1:nChi + nChiHea].y, scaFloConChiHea.u)
  connect(floCon[1:nChi].y, scaFloConChi.u)
  connect(onAndOpe.y, valChiWatMinByp[1:nChi].uEna)
  connect(cooOrDirAndOnAndOpe.y, valChiWatMinByp[nChi + 1:nChi + nChiHea].uEna)
  connect(heaAndOnAndOpe.y, valHeaWatMinByp.uEna)
  connect(floChiWatMin.y, valChiWatMinByp.u_s)
  connect(floHeaWatMin.y, valHeaWatMinByp.u_s)
  connect(max2.y, yValChiWatMinByp)
  connect(valChiWatMinByp.y, max2.u)
  connect(max3.y, yValHeaWatMinByp)
  connect(valHeaWatMinByp.y, max3.u)
  connect(mEvaChiHea_flow, valEvaChiHea.u_m)
  connect(mEvaChiHea_flow, valChiWatMinByp[nChi + 1:nChi + nChiHea].u_m)
  connect(mConChi_flow, valConChi.u_m)
  connect(mEvaChi_flow, valEvaChi.u_m)
  connect(mEvaChi_flow, valChiWatMinByp[1:nChi].u_m)
  connect(mConChiHea_flow, valConChiHea.u_m)
  connect(mConChiHea_flow, valHeaWatMinByp.u_m)
  connect(mEvaChiSet_flow, rep2.u)
  connect(rep2.y, valEvaChi.u_s)
  connect(anyDirHeaCooAndOn.y, rep7.u)
  connect(zer1.y, swi.u3)
  connect(u1Chi, swi.u2)
  connect(anyDirHeaCooAndOn.y, noHeaAndCooAndOn.u)
  connect(anyCooAndOn.y, and2.u1)
  connect(noHeaAndCooAndOn.y, and2.u2)
  connect(and2.y, rep8.u)
  connect(yBalChi.y, swi1.u1)
  connect(rep8.y, swi1.u2)
  connect(fulOpe.y, swi2.u2)
  connect(valEvaChi.y, swi2.u3)
  connect(rep7.y, valEvaChi.uEna)
  connect(one1.y, swi2.u1)
  connect(swi2.y, swi1.u3)
  connect(swi1.y, swi.u1)
  connect(swi.y, yValEvaChi)
  connect(heaAndOn.y, valEvaChiHea.uEna)
  connect(u1ChiHea, cooAndOn.u1)
  connect(u1CooChiHea, cooAndOn.u2)
  connect(cooAndOn.y, selValPos.u2)
  connect(yBalChiHea.y, selValPos.u1)
  connect(valEvaChiHea.y, selValPos.u3)
  connect(selValPos.y, yValEvaChiHea)
  connect(anyCooOrDirAndOn.y, rep13.u)
  connect(rep13.y, fulOpe.u)
  connect(cooOrDirAndOn.y, anyCooOrDirAndOn.u)
  connect(cooAndOn.y, anyCooAndOn.u)
  connect(cooAndOn.y, heaOrCooCon.u1)
  connect(cooAndOn.y, valConChiHea.uEna)
  connect(heaAndOn.y, booToRea.u)
  connect(max4.y, yValConChiHea)
  connect(booToRea.y, max4.u2)
  connect(valConChiHea.y, max4.u1)
  connect(isOpe3.y, isCloConChi.u)
  connect(isCloConChi.y, allCloAndChaAndEna.u[1:nChi])
  connect(enaCtlValConWatByp.y, yValConWatByp)
  connect(allCloAndChaAndEna.y, enaCtlValConWatByp.u2)
  connect(ctlTConWatConRet.y, enaCtlValConWatByp.u1)
  connect(isChaAss.y, allCloAndChaAndEna.u[nChi + 1])
  connect(zer2.y, enaCtlValConWatByp.u3)
  connect(yValConWatByp, isOpe4.u)
  connect(isOpe4.y, enaPumConWatCon.u[nChi+nChiHea+1])
  connect(u1CooOrHea, allCloAndChaAndEna.u[nChi+2])
end ValveCondenserEvaporator;


Package with validation models

within Buildings.DHC.Plants.Combined.Controls.BaseClasses;
package Validation "Package with validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Staging. This is a validation model for the block

Buildings.DHC.Plants.Combined.Controls.BaseClasses.StageIndex.

within Buildings.DHC.Plants.Combined.Controls.BaseClasses.Validation;
model StageIndex
  extends Modelica.Icons.Example;

  Buildings.DHC.Plants.Combined.Controls.BaseClasses.StageIndex
    sta(nSta=3, tSta=60) "Staging"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable booTimTab(
    table=[0,0,0,0; 1,1,0,0; 2,1,1,1; 3,0,1,1; 4,1,0,0; 5,1,0,1; 6,1,1,0; 7,1,0,
        1],
    timeScale=100,
    period=1000) "Source signal"
equation
  connect(booTimTab.y[1], sta.u1)
  connect(booTimTab.y[2], sta.u1Up)
  connect(booTimTab.y[3], sta.u1Dow)
end StageIndex;


Validation of plant staging block. This is a validation model for the plant staging logic implemented in

Buildings.DHC.Plants.Combined.Controls.BaseClasses.StagingPlant.

within Buildings.DHC.Plants.Combined.Controls.BaseClasses.Validation;
model StagingPlant "Validation of plant staging block"
  extends Modelica.Icons.Example;

  parameter Integer nChi(final min=1, start=1)=2
    "Number of units operating at design conditions"
  parameter Modelica.Units.SI.HeatFlowRate QChiWatChi_flow_nominal=-4.4E6
    "Cooling design heat flow rate of cooling-only chillers (all units)"
  parameter Integer nChiHea(final min=1, start=1)=3
    "Number of units operating at design conditions"
  parameter Real PLRStaTra(final unit="1", final min=0, final max=1) = 0.85
    "Part load ratio triggering stage transition";
  parameter Modelica.Units.SI.HeatFlowRate QChiWatCasCoo_flow_nominal=-6E6
    "Cooling design heat flow rate of HRC in cascading cooling mode (all units)"
  parameter Modelica.Units.SI.HeatFlowRate QHeaWat_flow_nominal=6.4E6
    "Heating design heat flow rate (all units)"
  final parameter Modelica.Units.SI.HeatFlowRate mChiWat_flow_nominal=
    abs(QChiWatChi_flow_nominal+QChiWatCasCoo_flow_nominal) /
    Buildings.Utilities.Psychrometrics.Constants.cpWatLiq /
    5
    "CHW design mass flow rate"
  final parameter Modelica.Units.SI.HeatFlowRate mHeaWat_flow_nominal=
    QHeaWat_flow_nominal /
    Buildings.Utilities.Psychrometrics.Constants.cpWatLiq /
    10
    "HW design mass flow rate"

  Buildings.DHC.Plants.Combined.Controls.BaseClasses.StagingPlant
    staChi(
    final nChi=nChi,
    final nChiHea=nChiHea,
    final QChiWatChi_flow_nominal=QChiWatChi_flow_nominal,
    final QChiWatCasCoo_flow_nominal=QChiWatCasCoo_flow_nominal,
    QChiWatCasCoo_flow_nominal_approx=QChiWatCasCoo_flow_nominal,
    final QHeaWat_flow_nominal=QHeaWat_flow_nominal) "Chiller staging block"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable ratFlo(table=[0,0,0; 1,
        0,0; 4,0.3,0.1; 5,1,0.1; 10,0.1,0.1; 13,1,0.3; 16,0.3,1;20,0.1,0.1; 24,0.1,0.3; 25,
        0.1,1; 30,0,0],
    timeScale=1000) "Source signal"
  Modelica.Blocks.Sources.BooleanExpression u1(y=time > 0)
    "Enable signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSupSet(k=7 + 273.15)
    "Source signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatPriRet(k=12 + 273.15)
    "Source signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSupSet(k=60 + 273.15)
    "Source signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatPriRet(k=50 + 273.15)
    "Source signal"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter sca(final k=
        mChiWat_flow_nominal) "Scale signal"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter sca1(final k=
        mHeaWat_flow_nominal) "Scale signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpSet(k=20E4)
    "Source signal"
equation
  connect(u1.y, staChi.u1Coo)
  connect(u1.y, staChi.u1Hea)
  connect(TChiWatSupSet.y, staChi.TChiWatSupSet)
  connect(THeaWatPriRet.y, staChi.THeaWatPriRet)
  connect(THeaWatSupSet.y, staChi.THeaWatSupSet)
  connect(TChiWatPriRet.y, staChi.TChiWatPriRet)
  connect(sca.y, staChi.mChiWatPri_flow)
  connect(sca1.y, staChi.mHeaWatPri_flow)
  connect(TChiWatSupSet.y, staChi.TChiWatSup)
  connect(dpSet.y, staChi.dpChiWat)
  connect(dpSet.y, staChi.dpChiWatSet)
  connect(dpSet.y, staChi.dpHeaWatSet)
  connect(dpSet.y, staChi.dpHeaWat)
  connect(THeaWatSupSet.y, staChi.THeaWatSup)
  connect(ratFlo.y[1], sca.u)
  connect(ratFlo.y[2], sca1.u)
end StagingPlant;


Validation of pump staging block. This is a validation model for the pump staging logic implemented in

Buildings.DHC.Plants.Combined.Controls.BaseClasses.StagingPump.

within Buildings.DHC.Plants.Combined.Controls.BaseClasses.Validation;
model StagingPump "Validation of pump staging block"
  extends Modelica.Icons.Example;

  parameter Integer nPum(
    final min=1,
    start=1)=3
    "Number of pumps"
  parameter Integer nChi(
    final min=1,
    start=1)=1
    "Number of chillers served by the pumps"
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=1

  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable floSpe(
    table=[
      0,0,0;
      1,0,0;
      4,(nPum - 1)/nPum*m_flow_nominal,1;
      5,m_flow_nominal,0.9;
      10,0,0.1],
    timeScale=500)
    "Source signal"
  Buildings.DHC.Plants.Combined.Controls.BaseClasses.StagingPump
    staDet(
    final nPum=nPum,
    final m_flow_nominal=m_flow_nominal)
    "Pump staging block - Detailed version"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yVal(k=1)
    "Source signal"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold isOpe(t=0.1,
    h=5E-2) "Check if valve open"
equation
  connect(floSpe.y[1],staDet. m_flow)
  connect(floSpe.y[2],staDet. y)
  connect(yVal.y, isOpe.u)
  connect(isOpe.y,staDet.y1Ena)
end StagingPump;


Condenser loop operating modes

within Buildings.DHC.Plants.Combined.Controls;
package ModeCondenserLoop "Condenser loop operating modes"

  constant Integer tankCharge = 1 "Tank Charge/Discharge";
  constant Integer chargeAssist = 2  "Charge Assist";
  constant Integer heatRejection = 3 "Heat Rejection";
end ModeCondenserLoop;


within Buildings.DHC.Plants.Combined.Examples;
model AllElectricCWStorage
  "Validation of all-electric plant model with buildings loads"
  extends Modelica.Icons.Example;

  replaceable package Medium=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Main medium (common to CHW, HW and CW)";
  replaceable package MediumConWatCoo=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Medium in cooler circuit";

  parameter String filNam[2]={"modelica://Buildings/Resources/Data/DHC/Loads/Examples/MediumOffice-90.1-2010-5A.mos",
                              "modelica://Buildings/Resources/Data/DHC/Loads/Examples/MediumOffice-90.1-2010-5A.mos"}
    "Path to file with timeseries loads";
  parameter Modelica.Units.SI.Temperature TSetDisSupHea = 273.15+60 "District heating supply temperature set point";
  parameter Modelica.Units.SI.Temperature TSetDisSupCoo = 273.15+6 "District cooling supply temperature set point";

  replaceable parameter
    Fluid.Chillers.Data.ElectricReformulatedEIR.ReformEIRChiller_Carrier_19XR_1403kW_7_09COP_VSD datChi(
      EIRFunT={0.0101739374, 0.0607200115, 0.0003348647, 0.003162578, 0.0002388594, -0.0014121289},
      capFunT={0.0387084662, 0.2305017927, 0.0004779504, 0.0178244359, -8.48808e-05, -0.0032406711},
      EIRFunPLR={0.4304252832, -0.0144718912, 5.12039e-05, -0.7562386674, 0.5661683373,
        0.0406987748, 3.0278e-06, -0.3413411197, -0.000469572, 0.0055009208},
    QEva_flow_nominal=sum(loaCoo.QCoo_flow_nominal)/pla.nChi,
      COP_nominal=2.5,
    mEva_flow_nominal=-datChi.QEva_flow_nominal/5/4186,
      mCon_flow_nominal=-datChi.QEva_flow_nominal * (1 + 1/datChi.COP_nominal) / 10 / 4186,
    TEvaLvg_nominal=TSetDisSupCoo,
    TEvaLvgMin=277.15,
    TEvaLvgMax=308.15,
    TConLvg_nominal=TSetDisSupHea,
    TConLvgMin=296.15,
    TConLvgMax=336.15)
    constrainedby Buildings.Fluid.Chillers.Data.BaseClasses.Chiller
    "Chiller parameters (each unit)"
  replaceable parameter Fluid.Chillers.Data.ElectricReformulatedEIR.Generic datChiHea = datChi
    constrainedby Buildings.Fluid.Chillers.Data.BaseClasses.Chiller
    "Chiller parameters (each unit)"
  replaceable parameter Fluid.HeatPumps.Data.EquationFitReversible.Generic datHeaPum(
    dpHeaLoa_nominal=50000,
    dpHeaSou_nominal=100,
    hea(
      mLoa_flow=datHeaPum.hea.Q_flow/10/4186,
      mSou_flow=1E-4*datHeaPum.hea.Q_flow,
      Q_flow=sum(loaHea.QHea_flow_nominal)/pla.nHeaPum,
      P=datHeaPum.hea.Q_flow/2.2,
      coeQ={-5.64420084,1.95212447,9.96663913,0.23316322,-5.64420084},
      coeP={-3.96682255,6.8419453,1.99606939,0.01393387,-3.96682255},
      TRefLoa=298.15,
      TRefSou=253.15),
    coo(
      mLoa_flow=0,
      mSou_flow=0,
      Q_flow=-1,
      P=0,
      coeQ=fill(0, 5),
      coeP=fill(0, 5),
      TRefLoa=273.15,
      TRefSou=273.15))
    "Heat pump parameters (each unit)"

  // Assumptions
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=
    Modelica.Fluid.Types.Dynamics.FixedInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"

  Buildings.DHC.Plants.Combined.AllElectricCWStorage pla(
    redeclare final package Medium = Medium,
    redeclare package MediumHea_b = Medium,
    redeclare final package MediumConWatCoo = MediumConWatCoo,
    allowFlowReversal=true,
    dpConWatCooFri_nominal=1E4,
    mAirCooUni_flow_nominal=pla.mConWatCoo_flow_nominal/pla.nCoo/1.45,
    TWetBulCooEnt_nominal=297.05,
    PFanCoo_nominal=340*pla.mConWatCoo_flow_nominal/pla.nCoo,
    chi(show_T=true),
    chiHea(show_T=true),
    heaPum(show_T=true),
    final datChi=datChi,
    final datChiHea=datChiHea,
    final datHeaPum=datHeaPum,
    nChi=2,
    dpChiWatSet_max=(sum(disCoo.lDis) + disCoo.lEnd)*disCoo.dp_length_nominal,
    nChiHea=2,
    dpHeaWatSet_max=(sum(disHea.lDis) + disHea.lEnd)*disHea.dp_length_nominal,
    nHeaPum=2,
    dInsTan=0.05,
    nCoo=3,
    final energyDynamics=energyDynamics)
    "CHW and HW plant"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSupSet(final k=pla.TChiWatSup_nominal,
    y(final unit="K", displayUnit="degC"))
                   "Source signal for setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSupSet(final k=pla.THeaWatSup_nominal,
    y(final unit="K", displayUnit="degC"))
                   "Source signal for setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpHeaWatSet_max(
    k=pla.dpHeaWatSet_max,
    y(final unit="Pa")) "Source signal for setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpChiWatSet_max(
    k=pla.dpChiWatSet_max,
    y(final unit="Pa")) "Source signal for setpoint"
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
    "Outdoor conditions"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatRet[2](each k=pla.TChiWatRet_nominal)
    "Source signal for CHW return temperature"
  Loads.Heating.BuildingTimeSeriesWithETS loaHea[2](
    each THeaWatSup_nominal=pla.THeaWatSup_nominal,
    filNam=filNam)                     "Building heating load"
    // dpCheVal_nominal to avoid too hot water in building waterr supply due to problem of temperature drop in Dymola
  Loads.Cooling.BuildingTimeSeriesWithETS loaCoo[2](
    each TChiWatSup_nominal=pla.TChiWatSup_nominal,
    filNam=filNam,
    each bui(w_aLoaCoo_nominal=0.015)) "Building cooling load"
    // dpCheVal_nominal to avoid freezing in building waterr supply due to problem of temperature drop in Dymola
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatRet[2](each k=pla.THeaWatRet_nominal)
    "Source signal for HW return temperature"
  Buildings.Controls.OBC.CDL.Logical.Not
                               onPla "On signal for the plant"
  Buildings.Controls.OBC.CDL.Logical.Timer
                                 tim(t=3600)
  Buildings.Controls.OBC.CDL.Reals.LessThreshold offHea(t=1e-4)
    "Threshold comparison to disable the plant"
  Modelica.Blocks.Math.Gain norQFloHea(k=1/sum(loaHea.QHea_flow_nominal))
    "Normalized Q_flow"
  Buildings.Controls.OBC.CDL.Logical.Not
                               onPla1
                                     "On signal for the plant"
  Buildings.Controls.OBC.CDL.Logical.Timer
                                 tim1(t=3600)
  Buildings.Controls.OBC.CDL.Reals.LessThreshold offCoo1(t=1e-4)
    "Threshold comparison to disable the plant"
  Modelica.Blocks.Math.Gain norQFloCoo(k=1/sum(loaCoo.QCoo_flow_nominal))
    "Normalized Q_flow"
  Buildings.DHC.Networks.Distribution2Pipe_R disHea(
    redeclare final package Medium = Medium,
    nCon=2,
    allowFlowReversal=false,
    mDis_flow_nominal=sum(loaHea.mBui_flow_nominal),
    mCon_flow_nominal={loaHea[1].mBui_flow_nominal,loaHea[2].mBui_flow_nominal},

    mEnd_flow_nominal=sum(loaHea.mBui_flow_nominal),
    lDis={800,200},
    lEnd=200) "Distribution network for district heating system"

  Buildings.DHC.Networks.Distribution2Pipe_R disCoo(
    redeclare final package Medium = Medium,
    nCon=2,
    allowFlowReversal=false,
    mDis_flow_nominal=sum(loaCoo.mBui_flow_nominal),
    mCon_flow_nominal={loaCoo[1].mBui_flow_nominal,loaCoo[2].mBui_flow_nominal},

    mEnd_flow_nominal=sum(loaCoo.mBui_flow_nominal),
    lDis={80,20},
    lEnd=20) "Distribution network for district cooling system"

  Modelica.Blocks.Math.Sum QTotHea_flow(nin=2)
    "Total heating flow rate for all buildings "
  Modelica.Blocks.Math.Sum QTotCoo_flow(nin=2)
    "Total cooling flow rate for all buildings "
equation
  connect(TChiWatSupSet.y, pla.TChiWatSupSet)
  connect(THeaWatSupSet.y, pla.THeaWatSupSet)
  connect(dpChiWatSet_max.y, pla.dpChiWatSet)
  connect(dpHeaWatSet_max.y, pla.dpHeaWatSet)

  connect(weaDat.weaBus, pla.weaBus)
  connect(norQFloHea.y,offHea. u)
  connect(offHea.y, tim.u)
  connect(tim.passed, onPla.u)
  connect(onPla.y, pla.u1Hea)
  connect(tim1.passed, onPla1.u)
  connect(offCoo1.y, tim1.u)
  connect(norQFloCoo.y, offCoo1.u)
  connect(onPla1.y, pla.u1Coo)
  connect(pla.port_bSerHea, disHea.port_aDisSup)
  connect(disHea.port_bDisRet, pla.port_aSerHea)
  connect(disCoo.port_aDisSup, pla.port_bSerCoo)
  connect(disCoo.port_bDisRet, pla.port_aSerCoo)
  connect(disCoo.ports_aCon, loaCoo.port_bSerCoo)
  connect(disCoo.ports_bCon, loaCoo.port_aSerCoo)
  connect(disHea.ports_bCon, loaHea.port_aSerHea)
  connect(loaHea.port_bSerHea, disHea.ports_aCon)
  connect(QTotHea_flow.y, norQFloHea.u)
  connect(loaCoo.QCoo_flow, QTotCoo_flow.u)
  connect(QTotCoo_flow.y, norQFloCoo.u)
  connect(loaHea.QHea_flow, QTotHea_flow.u)
  connect(TChiWatRet.y,loaCoo.TDisRetSet)
  connect(THeaWatRet.y,loaHea.TDisRetSet)
end AllElectricCWStorage;


within Buildings.DHC.Plants.Combined;
package Examples "This package holds example models using plants providing district heating and cooling"
  extends Modelica.Icons.ExamplesPackage;
end Examples;