Controller for AWHP plant. This block implements the sequence of operation for plants with
air-to-water heat pumps.
Most parts of the sequence of operation are similar to that
described in ASHRAE, 2021 for chiller plants.

within Buildings.Templates.Plants.Controls.HeatPumps;
block AirToWater
  "Controller for AWHP plant"
  parameter Boolean have_heaWat
    "Set to true for plants that provide HW"
  parameter Boolean have_chiWat
    "Set to true for plants that provide CHW"
  parameter Boolean is_priOnl=false
    "Set to true for primary-only plant"
  parameter Boolean have_hrc_select(start=false)=false
    "Set to true for plants with sidestream heat recovery chiller"
  final parameter Boolean have_hrc=if have_heaWat and have_chiWat then have_hrc_select
    else false
    "Set to true for plants with sidestream heat recovery chiller"
  parameter Boolean have_valHpInlIso
    "Set to true for plants with isolation valves at heat pump inlet"
  parameter Boolean have_valHpOutIso
    "Set to true for plants with isolation valves at heat pump outlet"
  final parameter Boolean have_pumHeaWatPri=have_heaWat
    "Set to true for plants with primary HW pumps"
  parameter Boolean have_pumChiWatPriDed_select(start=false)=false
    "Set to true for plants with separate dedicated primary CHW pumps"
  final parameter Boolean have_pumChiWatPriDed=
    if have_chiWat and not have_pumPriHdr then have_pumChiWatPriDed_select else false
    "Set to true for plants with separate dedicated primary CHW pumps"
  final parameter Boolean have_pumChiWatPri=
    have_chiWat and (have_pumPriHdr or have_pumChiWatPriDed)
    "Set to true for plants with separate primary CHW pumps"
  parameter Boolean have_pumPriHdr
    "Set to true for headered primary pumps, false for dedicated pumps"
  parameter Boolean have_pumHeaWatPriVar_select(start=true)=true
    "Set to true for variable speed primary HW pumps, false for constant speed pumps"
  parameter Boolean have_pumChiWatPriVar_select(start=true)=true
    "Set to true for variable speed primary CHW pumps, false for constant speed pumps"
  final parameter Boolean have_pumHeaWatPriVar=
    have_pumHeaWatPri and (is_priOnl or have_pumHeaWatPriVar_select)
    "Set to true for variable speed primary HW pumps, false for constant speed pumps"
  final parameter Boolean have_pumChiWatPriVar=
    have_pumChiWatPri and (is_priOnl or have_pumChiWatPriVar_select)
    "Set to true for variable speed primary CHW pumps, false for constant speed pumps"
  final parameter Boolean have_pumPriCtlDp=is_priOnl
    "Set to true for primary variable speed pumps using ∆p pump speed control"
  final parameter Boolean have_pumHeaWatSec=
    have_heaWat and not is_priOnl
    "Set to true for plants with secondary HW pumps"
  final parameter Boolean have_pumChiWatSec=
    have_chiWat and not is_priOnl
    "Set to true for plants with secondary CHW pumps"
  // Only headered arrangements are supported for secondary pumps.
  final parameter Boolean have_pumSecHdr=true
    "Set to true for headered secondary pumps, false for dedicated pumps"
  // Only ∆p controlled variable speed pumps are supported for secondary pumps.
  final parameter Boolean have_pumSecCtlDp=have_pumHeaWatSec or have_pumChiWatSec
    "Set to true for secondary variable speed pumps using ∆p pump speed control"
  parameter Boolean have_senVHeaWatPri_select(start=false)
    "Set to true for plants with primary HW flow sensor"
  final parameter Boolean have_senVHeaWatPri=have_heaWat and
    (if have_hrc or not have_senVHeaWatSec then true else have_senVHeaWatPri_select)
    "Set to true for plants with primary HW flow sensor"
  // Secondary flow sensor required for secondary HW pump staging.
  final parameter Boolean have_senVHeaWatSec=have_pumHeaWatSec
    "Set to true for plants with secondary HW flow sensor"
  parameter Boolean have_senVChiWatPri_select(start=false)
    "Set to true for plants with primary CHW flow sensor"
  final parameter Boolean have_senVChiWatPri=have_chiWat and
    (if have_hrc or not have_senVChiWatSec then true
    else have_senVChiWatPri_select)
    "Set to true for plants with primary CHW flow sensor"
  // Secondary flow sensor required for secondary CHW pump staging.
  final parameter Boolean have_senVChiWatSec(start=false)=have_pumChiWatSec
    "Set to true for plants with secondary CHW flow sensor"
  parameter Boolean have_senTHeaWatPriRet_select(start=false)
    "Set to true for plants with primary HW return temperature sensor"
  final parameter Boolean have_senTHeaWatPriRet=have_heaWat and
    (if have_hrc or not have_senTHeaWatSecRet then true else have_senTHeaWatPriRet_select)
    "Set to true for plants with primary HW return temperature sensor"
  parameter Boolean have_senTChiWatPriRet_select(start=false)
    "Set to true for plants with primary CHW return temperature sensor"
  final parameter Boolean have_senTChiWatPriRet=have_chiWat and
    (if have_hrc or not have_senTChiWatSecRet then true else have_senTChiWatPriRet_select)
    "Set to true for plants with primary CHW return temperature sensor"
  // For primary-secondary plants, SHWST sensor is required for plant staging.
  final parameter Boolean have_senTHeaWatSecSup=have_pumHeaWatSec
    "Set to true for plants with secondary HW supply temperature sensor"
  // For primary-secondary plants, SCHWST sensor is required for plant staging.
  final parameter Boolean have_senTChiWatSecSup=have_pumChiWatSec
    "Set to true for plants with secondary CHW supply temperature sensor"
  // Following return temperature sensors are:
  // - optional for primary-secondary plants without HRC,
  // - required for plants with HRC: downstream of HRC.
  parameter Boolean have_senTHeaWatSecRet_select(start=false)=false
    "Set to true for plants with secondary HW return temperature sensor"
  parameter Boolean have_senTChiWatSecRet_select(start=false)=false
    "Set to true for plants with secondary CHW return temperature sensor"
  final parameter Boolean have_senTHeaWatSecRet=
    if have_hrc then true
    elseif not have_pumHeaWatSec then false
    else have_senTHeaWatSecRet_select
    "Set to true for plants with secondary HW return temperature sensor"
  final parameter Boolean have_senTChiWatSecRet(start=false)=
    if have_hrc then true
    elseif not have_pumChiWatSec then false
    else have_senTChiWatSecRet_select
    "Set to true for plants with secondary CHW return temperature sensor"
  parameter Integer nHp(min=1)
    "Number of heat pumps"
  parameter Integer nPumHeaWatPri(
    min=if have_pumHeaWatPri then 1 else 0,
    start=0)=nHp
    "Number of primary HW pumps"
  parameter Integer nPumChiWatPri(
    min=if have_pumChiWatPri then 1 else 0,
    start=if have_pumChiWatPri then nHp else 0)=if have_pumChiWatPri then nHp
     else 0
    "Number of primary CHW pumps"
  parameter Integer nPumHeaWatSec(
    min=if have_pumHeaWatSec then 1 else 0,
    start=0)=nHp
    "Number of secondary HW pumps"
  parameter Integer nPumChiWatSec(
    min=if have_pumChiWatSec then 1 else 0,
    start=0)=nHp
    "Number of secondary CHW pumps"
  parameter Boolean have_senDpHeaWatRemWir(start=false)=false
    "Set to true for remote HW differential pressure sensor(s) hardwired to plant or pump controller"
  parameter Integer nSenDpHeaWatRem(
    final min=if have_heaWat then 1 else 0,
    start=0)
    "Number of remote HW differential pressure sensors used for HW pump speed control"
  parameter Boolean have_senDpChiWatRemWir(start=false)=false
    "Set to true for remote CHW differential pressure sensor(s) hardwired to plant or pump controller"
  parameter Integer nSenDpChiWatRem(
    final min=if have_chiWat then 1 else 0,
    start=0)
    "Number of remote CHW differential pressure sensors used for CHW pump speed control"
  parameter Real THeaWatSup_nominal(
    min=273.15,
    start=50 + 273.15,
    unit="K",
    displayUnit="degC")
    "Design HW supply temperature (maximum setpoint)"
  parameter Real THeaWatSupSet_min(
    min=273.15,
    start=25 + 273.15,
    unit="K",
    displayUnit="degC")
    "Minimum value to which the HW supply temperature can be reset"
  parameter Real TOutHeaWatLck(
    min=273.15,
    start=21 + 273.15,
    unit="K",
    displayUnit="degC")=294.15
    "Outdoor air lockout temperature above which the HW loop is prevented from operating"
  parameter Real capHeaHp_nominal[nHp](
    min=fill(0, nHp),
    start=fill(1, nHp),
    unit=fill("W", nHp))
    "Design heat pump heating capacity - Each heat pump"
  parameter Real VHeaWatHp_flow_nominal[nHp](
    final min=fill(0, nHp),
    start=fill(1E-6, nHp),
    final unit=fill("m3/s", nHp))
    "Design heat pump HW volume flow rate - Each heat pump"
  parameter Real VHeaWatHp_flow_min[nHp](
    final min=fill(0, nHp),
    start=fill(0, nHp),
    final unit=fill("m3/s", nHp))
    "Minimum heat pump HW volume flow rate - Each heat pump"
  parameter Real VHeaWatPri_flow_nominal(
    min=0,
    start=sum(VHeaWatHp_flow_nominal),
    unit="m3/s")=sum(VHeaWatHp_flow_nominal)
    "Primary HW volume flow rate"
  parameter Real VHeaWatSec_flow_nominal(
    min=0,
    start=1E-6,
    unit="m3/s")
    "Design secondary HW volume flow rate"
  parameter Real dpHeaWatRemSet_max[nSenDpHeaWatRem](
    min=fill(0, nSenDpHeaWatRem),
    start=fill(5E4, nSenDpHeaWatRem),
    unit=fill("Pa", nSenDpHeaWatRem))
    "Maximum HW differential pressure setpoint - Remote sensor"
  parameter Real dpHeaWatRemSet_min(
    min=0,
    start=5*6894,
    unit="Pa")=5*6894
    "Minimum value to which the HW differential pressure can be reset - Remote sensor"
  parameter Real yPumHeaWatPriSet(
    max=2,
    min=0,
    start=1,
    unit="1")
    "Primary pump speed providing design heat pump flow in heating mode"
  parameter Real TChiWatSup_nominal(
    min=273.15,
    start=7 + 273.15,
    unit="K",
    displayUnit="degC")
    "Design CHW supply temperature (minimum setpoint)"
  parameter Real TChiWatSupSet_max(
    min=273.15,
    start=15 + 273.15,
    unit="K",
    displayUnit="degC")
    "Maximum value to which the CHW supply temperature can be reset"
  parameter Real TOutChiWatLck(
    min=273.15,
    start=16 + 273.15,
    unit="K",
    displayUnit="degC")=289.15
    "Outdoor air lockout temperature below which the CHW loop is prevented from operating"
  parameter Real capCooHp_nominal[nHp](
    min=fill(0, nHp),
    start=fill(1, nHp),
    unit=fill("W", nHp))
    "Design heat pump cooling capacity - Each heat pump"
  parameter Real VChiWatHp_flow_nominal[nHp](
    final min=fill(0, nHp),
    start=fill(1E-6, nHp),
    final unit=fill("m3/s", nHp))
    "Design heat pump CHW volume flow rate - Each heat pump"
  parameter Real VChiWatHp_flow_min[nHp](
    final min=fill(0, nHp),
    start=fill(0, nHp),
    final unit=fill("m3/s", nHp))
    "Minimum heat pump CHW volume flow rate - Each heat pump"
  parameter Real VChiWatPri_flow_nominal(
    final min=0,
    start=sum(VChiWatHp_flow_nominal),
    final unit="m3/s")=sum(VChiWatHp_flow_nominal)
    "Primary CHW volume flow rate"
  parameter Real VChiWatSec_flow_nominal(
    min=0,
    start=1E-6,
    unit="m3/s")
    "Design secondary CHW volume flow rate"
  parameter Real dpChiWatRemSet_max[nSenDpChiWatRem](
    min=fill(0, nSenDpChiWatRem),
    start=fill(5E4, nSenDpChiWatRem),
    unit=fill("Pa", nSenDpChiWatRem))
    "Maximum CHW differential pressure setpoint - Remote sensor"
  parameter Real dpChiWatRemSet_min(
    min=0,
    start=5*6894,
    unit="Pa")=5*6894
    "Minimum value to which the CHW differential pressure can be reset - Remote sensor"
  parameter Real yPumChiWatPriSet(
    max=2,
    min=0,
    start=1,
    unit="1")
    "Primary pump speed providing design heat pump flow in cooling mode"
  parameter Real cp_default(
    min=0,
    unit="J/(kg.K)")=4184
    "Default specific heat capacity used to compute required capacity"
  parameter Real rho_default(
    min=0,
    unit="kg/m3")=996
    "Default density used to compute required capacity"
  parameter Boolean have_inpSch=false
    "Set to true to provide schedule via software input point"
  parameter Real schHea[:, 2](start=[0,1; 24*3600,1])=[0,1; 24*3600,1]
    "Heating mode enable schedule"
  parameter Real schCoo[:, 2](start=[0,1; 24*3600,1])=[0,1; 24*3600,1]
    "Cooling mode enable schedule"
  parameter Integer nReqIgnHeaWat(min=0)=0
    "Number of ignored HW plant requests"
  parameter Integer nReqIgnChiWat(min=0)=0
    "Number of ignored CHW plant requests"
  parameter Real dTOutLck(
    min=0,
    unit="K")=0.5
    "Hysteresis for outdoor air lockout temperature"
  parameter Real dtRunEna(
    min=0,
    unit="s")=15*60
    "Minimum runtime of enable and disable states"
  parameter Real dtReqDis(
    min=0,
    unit="s")=3*60
    "Runtime with low number of request before disabling"
  parameter Real staEqu[:, nHp](
    each final max=1,
    each final min=0,
    each final unit="1")
    "Staging matrix – Equipment required for each stage"
  final parameter Integer nSta(
    final min=1)=size(staEqu, 1)
    "Number of stages"
  final parameter Integer nEquAlt(
    final min=0)=if nHp==1 then 1 else
    max({sum({(if staEqu[i, j] > 0 and staEqu[i, j] < 1 then 1 else 0) for j in 1:nHp}) for i in 1:nSta})
    "Number of lead/lag alternate equipment"
  parameter Integer idxEquAlt[nEquAlt](final min=fill(1, nEquAlt))
    "Indices of lead/lag alternate equipment"
  parameter Real plrSta(
    max=1,
    min=0,
    start=0.9,
    unit="1")=0.9
    "Staging part load ratio"
  parameter Real dTHea(
    min=0,
    unit="K")=2.5
    "Delta-T triggering stage up command for heating appplications (>0)"
  parameter Real dTCoo(
    min=0,
    unit="K")=1
    "Delta-T triggering stage up command for cooling applications (>0)"
  parameter Real dtVal(
    min=0,
    start=90,
    unit="s")=90
    "Nominal valve timing"
  parameter Real dtRunSta(
    min=0,
    unit="s",
    displayUnit="min")=900
    "Minimum runtime of each stage"
  parameter Real dtOff(
    min=0,
    unit="s")=900
    "Off time required before equipment is deemed available again"
  parameter Real dtOffHp(
    min=0,
    unit="s")=180
    "Heat pump internal shutdown cycle timing (before closing isolation valves or disabling primary pumps)"
  parameter Real dtPri(
    min=0,
    unit="s")=900
    "Runtime with high primary-setpoint Delta-T before staging up"
  parameter Real dtSec(
    min=0,
    start=600,
    unit="s")=600
    "Runtime with high secondary-primary and secondary-setpoint Delta-T before staging up"
  parameter Real dtRunPumSta(
    min=0,
    start=600,
    unit="s")=600
    "Runtime before triggering stage change command based on efficiency condition"
  parameter Real dtRunFaiSafPumSta(
    min=0,
    start=300,
    unit="s")=300
    "Runtime before triggering stage change command based on failsafe condition"
  parameter Real dtRunFaiSafLowYPumSta(
    min=0,
    start=600,
    unit="s")=dtRunPumSta
    "Runtime before triggering stage change command based on low pump speed failsafe condition"
  parameter Real dVOffUpPumSta(
    max=1,
    min=0,
    start=0.03,
    unit="1")=0.03
    "Stage up flow point offset"
  parameter Real dVOffDowPumSta(
    max=1,
    min=0,
    start=0.03,
    unit="1")=dVOffUpPumSta
    "Stage down flow point offset"
  parameter Real dpOffPumSta(
    min=0,
    start=1E4,
    unit="Pa")=1E4
    "Stage change ∆p point offset (>0)"
  parameter Real yUpPumSta(
    min=0,
    start=0.99,
    unit="1")=0.99
    "Stage up pump speed point"
  parameter Real yDowPumSta(
    min=0,
    start=0.4,
    unit="1")=0.4
    "Stage down pump speed point"
  parameter Real dtHol(
    min=0,
    unit="s")=900
    "Minimum hold time during stage change"
  parameter Real resDpHeaWat_max(
    max=1,
    min=0,
    unit="1")=0.5
    "Upper limit of plant reset interval for HW differential pressure reset"
  parameter Real resTHeaWatSup_min(
    max=1,
    min=0,
    unit="1")=resDpHeaWat_max
    "Lower limit of plant reset interval for HW supply temperature reset"
  parameter Real resDpChiWat_max(
    max=1,
    min=0,
    unit="1")=0.5
    "Upper limit of plant reset interval for CHW differential pressure reset"
  parameter Real resTChiWatSup_min(
    max=1,
    min=0,
    unit="1")=resDpChiWat_max
    "Lower limit of plant reset interval for CHW supply temperature reset"
  parameter Real res_init(
    max=1,
    min=0,
    unit="1")=1
    "Initial reset value"
  parameter Real res_min(
    max=1,
    min=0,
    unit="1")=0
    "Minimum reset value"
  parameter Real res_max(
    max=1,
    min=0,
    unit="1")=1
    "Maximum reset value"
  parameter Real dtDel(
    min=100*1E-15,
    unit="s")=900
    "Delay time before the reset begins"
  parameter Real dtResHeaWat(
    min=1E-3,
    unit="s")=300
    "Time step for HW plant reset"
  parameter Integer nReqResIgnHeaWat(min=0)=2
    "Number of ignored requests for HW plant reset"
  parameter Real triHeaWat(
    max=0,
    unit="1")=-0.02
    "Trim amount for HW plant reset"
  parameter Real rspHeaWat(
    min=0,
    unit="1")=0.03
    "Respond amount for HW plant reset"
  parameter Real rspHeaWat_max(
    min=0,
    unit="1")=0.07
    "Maximum response per time interval for HW plant reset"
  parameter Real dtResChiWat(
    min=1E-3,
    unit="s")=300
    "Time step for CHW plant reset"
  parameter Integer nReqResIgnChiWat(min=0)=2
    "Number of ignored requests for CHW plant reset"
  parameter Real triChiWat(
    max=0,
    unit="1")=-0.02
    "Trim amount for CHW plant reset"
  parameter Real rspChiWat(
    min=0,
    unit="1")=0.03
    "Respond amount for CHW plant reset"
  parameter Real rspChiWat_max(
    min=0,
    unit="1")=0.07
    "Maximum response per time interval for CHW plant reset"
  parameter Real yPumHeaWatPri_min(
    max=1,
    min=0,
    start=0.1,
    unit="1")=0.1
    "Minimum primary HW pump speed"
  parameter Real kCtlDpHeaWat(
    min=100*Buildings.Controls.OBC.CDL.Constants.eps,
    start=1)=1
    "Gain of controller for HW loop ∆p control"
  parameter Real TiCtlDpHeaWat(
    min=100*Buildings.Controls.OBC.CDL.Constants.eps,
    start=60,
    unit="s")=60
    "Time constant of integrator block for HW loop ∆p control"
  parameter Real yPumChiWatPri_min(
    max=1,
    min=0,
    start=0.1,
    unit="1")=0.1
    "Minimum primary CHW pump speed"
  parameter Real kCtlDpChiWat(
    min=100*Buildings.Controls.OBC.CDL.Constants.eps,
    start=1)=1
    "Gain of controller for CHW loop ∆p control"
  parameter Real TiCtlDpChiWat(
    min=100*Buildings.Controls.OBC.CDL.Constants.eps,
    start=60,
    unit="s")=60
    "Time constant of integrator block for CHW loop ∆p control"
  parameter Real yPumHeaWatSec_min(
    max=1,
    min=0,
    start=0.1,
    unit="1")=0.1
    "Minimum secondary HW pump speed"
  parameter Real yPumChiWatSec_min(
    max=1,
    min=0,
    start=0.1,
    unit="1")=0.1
    "Minimum secondary CHW pump speed"
  parameter Real kValMinByp(
    min=0,
    start=1)=1
    "Gain of controller"
  parameter Modelica.Units.SI.Time TiValMinByp(
    min=Buildings.Controls.OBC.CDL.Constants.small,
    start=0.5)=60
    "Time constant of integrator block"
  // Sidestream HRC parameters
  parameter Boolean have_reqFloHrc(start=false)=false
    "Set to true if HRC provides flow request point via network interface"
  parameter Real TChiWatSupHrc_min(
    min=273.15,
    start=4 + 273.15,
    unit="K",
    displayUnit="degC")
    "Sidestream HRC – Minimum allowable CHW supply temperature"
  parameter Real THeaWatSupHrc_max(
    min=273.15,
    start=60 + 273.15,
    unit="K",
    displayUnit="degC")
    "Sidestream HRC – Maximum allowable HW supply temperature"
  parameter Real COPHeaHrc_nominal(
    min=1.1,
    start=2.8,
    unit="1")
    "Sidestream HRC – Heating COP at design heating conditions"
  parameter Real capCooHrc_min(
    min=0,
    start=0,
    unit="W")
    "Sidestream HRC – Minimum cooling capacity below which cycling occurs"
  parameter Real capHeaHrc_min(
    min=0,
    start=0,
    unit="W")
    "Sidestream HRC – Minimum heating capacity below which cycling occurs"
  parameter Real dtLoaHrc(
    min=0,
    start=600,
    unit="s")=600
    "Runtime with sufficient load before enabling"
  parameter Real dtTem1Hrc(
    min=0,
    start=180,
    unit="s")=180
    "Runtime with first temperature threshold exceeded before disabling"
  parameter Real dtTem2Hrc(
    min=0,
    start=60,
    unit="s")=60
    "Runtime with second temperature threshold exceeded before disabling"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant u1AvaHp[nHp](each k=true)
    "Heat pump available signal – Block does not handle faulted equipment yet"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nReqPlaHeaWat
    if have_heaWat
    "Number of HW plant requests"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TOut(
    final unit="K",
    final quantity="ThermodynamicTemperature",
    displayUnit="degC")
    "Outdoor air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SchHea
    if have_heaWat and have_inpSch
    "Heating mode enable via schedule"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nReqPlaChiWat
    if have_chiWat
    "Number of CHW plant requests"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SchCoo
    if have_chiWat and have_inpSch
    "Cooling mode enable via schedule"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nReqResHeaWat
    if have_heaWat
    "Sum of HW reset requests of all heating loads served"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput nReqResChiWat
    if have_chiWat
    "Sum of CHW reset requests of all heating loads served"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumHeaWatPri_actual[nPumHeaWatPri]
    if have_pumHeaWatPri
    "Primary HW pump status"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumChiWatPri_actual[nPumChiWatPri]
    if have_pumChiWatPri
    "Primary CHW pump status"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumHeaWatSec_actual[nPumHeaWatSec]
    if have_pumHeaWatSec
    "Secondary HW pump status"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumChiWatSec_actual[nPumChiWatSec]
    if have_pumChiWatSec
    "Secondary CHW pump status"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatPriRet(
    final unit="K",
    displayUnit="degC") if have_heaWat and have_senTHeaWatPriRet
    "Primary HW return temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VHeaWatPri_flow(
    final unit="m3/s") if have_heaWat and have_senVHeaWatPri
    "Primary HW volume flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHeaWatLoc(
    final unit="Pa")
    if have_heaWat and not have_senDpHeaWatRemWir
    "Local HW differential pressure"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHeaWatLocSet[nSenDpHeaWatRem](
    each final unit="Pa")
    if have_heaWat and not have_senDpHeaWatRemWir
    "Local HW differential pressure setpoint output from each of the remote loops"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpHeaWatRem[nSenDpHeaWatRem](
    each final unit="Pa") if have_heaWat and have_senDpHeaWatRemWir
    "Remote HW differential pressure"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatLoc(
    final unit="Pa")
    if have_chiWat and not have_senDpChiWatRemWir
    "Local CHW differential pressure"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatLocSet[nSenDpChiWatRem](
    each final unit="Pa")
    if have_chiWat and not have_senDpChiWatRemWir
    "Local CHW differential pressure setpoint output from each of the remote loops"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput dpChiWatRem[nSenDpChiWatRem](
    each final unit="Pa") if have_chiWat and have_senDpChiWatRemWir
    "Remote CHW differential pressure"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ValHeaWatHpInlIso[nHp]
    if have_heaWat and have_valHpInlIso
    "Heat pump inlet HW inlet isolation valve command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ValHeaWatHpOutIso[nHp]
    if have_heaWat and have_valHpOutIso
    "Heat pump outlet HW isolation valve command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ValChiWatHpInlIso[nHp]
    if have_chiWat and have_valHpInlIso
    "Heat pump inlet CHW isolation valve command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1ValChiWatHpOutIso[nHp]
    if have_chiWat and have_valHpOutIso
    "Heat pump outlet CHW isolation valve command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumHeaWatPri[nPumHeaWatPri]
    if have_pumHeaWatPri
    "Primary HW pump start command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumChiWatPri[nPumChiWatPri]
    if have_pumChiWatPri and have_chiWat
    "Primary CHW pump start command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumHeaWatSec[nPumHeaWatSec]
    if have_pumHeaWatSec
    "Secondary HW pump start command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumChiWatSec[nPumChiWatSec]
    if have_pumChiWatSec
    "Secondary CHW pump start command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Hp[nHp]
    "Heat pump enable command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1HeaHp[nHp]
    if have_heaWat and have_chiWat
    "Heat pump heating/cooling mode command: true=heating, false=cooling"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dpHeaWatRemSet[nSenDpHeaWatRem](
    each final min=0,
    each final unit="Pa") if have_heaWat
    "HW differential pressure setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dpChiWatRemSet[nSenDpChiWatRem](
    each final min=0,
    each final unit="Pa") if have_chiWat
    "CHW differential pressure setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumHeaWatPriHdr(
    final unit="1") if have_pumHeaWatPriVar and have_pumPriHdr
    "Primary headered HW pump speed command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumChiWatPriHdr(
    final unit="1") if have_pumChiWatPriVar and have_pumPriHdr
    "Primary headered CHW pump speed command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumHeaWatSec(
    final unit="1")
    if have_pumHeaWatSec
    "Primary HW pump speed command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumChiWatSec(
    final unit="1") if have_pumChiWatSec
    "Primary CHW pump speed command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TChiWatSupSet(
    final unit="K",
    displayUnit="degC") if have_chiWat
    "CHW supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput THeaWatSupSet(
    final unit="K",
    displayUnit="degC") if have_heaWat
    "HW supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatPriRet(
    final unit="K",
    displayUnit="degC") if have_chiWat and have_senTChiWatPriRet
    "Primary CHW return temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWatPri_flow(
    final unit="m3/s") if have_chiWat and have_senVChiWatPri
    "Primary CHW volume flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Hp_actual[nHp]
    "Heat pump status"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumHeaWatPriDed[nPumHeaWatPri](
    each final unit="1") if have_pumHeaWatPriVar and not have_pumPriHdr
    "Primary dedicated HW pump speed command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yPumChiWatPriDed[nPumChiWatPri](
    each final unit="1") if have_pumChiWatPriVar and have_pumChiWatPriDed
    "Primary dedicated CHW pump speed command"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatSecRet(
    final unit="K",
    displayUnit="degC") if have_heaWat and have_senTHeaWatSecRet
    "Secondary HW return temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VHeaWatSec_flow(
    final unit="m3/s") if have_heaWat and have_senVHeaWatSec
    "Secondary HW volume flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSecRet(
    final unit="K",
    displayUnit="degC") if have_chiWat and have_senTChiWatSecRet
    "Secondary CHW return temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWatSec_flow(
    final unit="m3/s") if have_chiWat and have_senVChiWatSec
    "Secondary CHW volume flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TSupSet[nHp](
    each final unit="K",
    each final quantity="ThermodynamicTemperature",
    each displayUnit="degC")
    "Active HP supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatPriSup(final unit="K",
      displayUnit="degC") if have_heaWat "Primary HW supply temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatPriSup(final unit="K",
      displayUnit="degC") if have_chiWat "Primary CHW return temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatSecSup(final unit="K",
      displayUnit="degC") if have_heaWat and have_senTHeaWatSecSup
    "Secondary HW supply temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSecSup(final unit="K",
      displayUnit="degC") if have_chiWat and have_senTChiWatSecSup
    "Secondary CHW return temperature"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Hrc if have_hrc
    "Sidestream HRC enable command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1CooHrc if have_hrc
    "Sidestream HRC mode command: true for cooling, false for heating"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumChiWatHrc if
    have_hrc
    "Sidestream HRC CHW pump enable command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumHeaWatHrc if
    have_hrc
    "Sidestream HRC HW pump enable command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TSupSetHrc(final unit="K",
      displayUnit="degC") if have_hrc
                          "Sidestream HRC active supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatRetUpsHrc(final unit="K",
      displayUnit="degC") if have_hrc "CHW return temperature upstream of HRC"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatRetUpsHrc(final unit="K",
      displayUnit="degC") if have_hrc "HW return temperature upstream of HRC"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Hrc_actual if have_hrc
    "HRC status"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1ReqFloChiWat
    if have_hrc and have_reqFloHrc
                   "CHW flow request from HRC"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1ReqFloConWat
    if have_hrc and have_reqFloHrc
                   "CW flow request from HRC"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValHeaWatMinByp(final unit="1")
    if have_heaWat and is_priOnl
    "HW minimum flow bypass valve command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yValChiWatMinByp(final unit="1")
    if have_chiWat and is_priOnl
    "CHW minimum flow bypass valve command"

  Enabling.Enable enaHea(
    final typ=Buildings.Templates.Plants.Controls.Types.Application.Heating,
    final TOutLck=TOutHeaWatLck,
    final dTOutLck=dTOutLck,
    final dtReq=dtReqDis,
    final dtRun=dtRunEna,
    final have_inpSch=have_inpSch,
    final nReqIgn=nReqIgnHeaWat,
    final sch=schHea)
    if have_heaWat
    "Heating mode enable"
  Utilities.StageIndex idxStaHea(
    final nSta=nSta,
    final dtRun=dtRunSta)
    if have_heaWat
    "Compute heating stage index"
  StagingRotation.StageAvailability avaStaHea(
    final staEqu=staEqu)
    if have_heaWat
    "Evaluate heating stage availability"
  StagingRotation.EquipmentEnable enaEquHea(
    final staEqu=staEqu, final nEquAlt=nEquAlt)
    if have_heaWat
    "Compute enable command for equipment in heating mode"
  StagingRotation.EventSequencing seqEve[nHp](
    each final have_heaWat=have_heaWat,
    each final have_chiWat=have_chiWat,
    each final have_valInlIso=have_valHpInlIso,
    each final have_valOutIso=have_valHpOutIso,
    each final have_pumHeaWatPri=have_pumHeaWatPri,
    each final have_pumChiWatPri=have_pumChiWatPri,
    each final have_pumHeaWatSec=have_pumHeaWatSec,
    each final have_pumChiWatSec=have_pumChiWatSec,
    each final dtVal=dtVal,
    each final dtOff=dtOffHp)
    "Event sequencing"
  StagingRotation.StageAvailability avaStaCoo(
    final staEqu=staEqu)
    if have_chiWat
    "Evaluate cooling stage availability"
  StagingRotation.StageChangeCommand chaStaHea(
    typ=Buildings.Templates.Plants.Controls.Types.Application.Heating,
    final have_pumSec=have_pumHeaWatSec,
    final have_inpPlrSta=false,
    final plrSta=plrSta,
    final staEqu=staEqu,
    final capEqu=capHeaHp_nominal,
    final dtRun=dtRunSta,
    final cp_default=cp_default,
    final rho_default=rho_default,
    final dT=dTHea,
    final dtPri=dtPri,
    final dtSec=dtSec) if have_heaWat
    "Generate heating stage transition command"
  StagingRotation.SortRuntime sorRunTimHea(
    idxEquAlt=idxEquAlt,
    nin=nHp)
    if have_heaWat
    "Sort lead/lag alternate equipment by staging runtime – Heating mode"
  Enabling.Enable enaCoo(
    final typ=Buildings.Templates.Plants.Controls.Types.Application.Cooling,
    final TOutLck=TOutChiWatLck,
    final dTOutLck=dTOutLck,
    final dtReq=dtReqDis,
    final dtRun=dtRunEna,
    final have_inpSch=have_inpSch,
    final nReqIgn=nReqIgnChiWat,
    final sch=schCoo)
    if have_chiWat
    "Cooling mode enable"
  StagingRotation.StageChangeCommand chaStaCoo(
    final typ=Buildings.Templates.Plants.Controls.Types.Application.Cooling,
    final have_pumSec=have_pumChiWatSec,
    final have_inpPlrSta=false,
    final plrSta=plrSta,
    final staEqu=staEqu,
    final capEqu=capCooHp_nominal,
    final dtRun=dtRunSta,
    final cp_default=cp_default,
    final rho_default=rho_default,
    final dT=dTCoo,
    final dtPri=dtPri,
    final dtSec=dtSec) if have_chiWat
    "Generate cooling stage transition command"
  Utilities.StageIndex idxStaCoo(
    final nSta=nSta,
    final dtRun=dtRunSta)
    if have_chiWat
    "Compute cooling stage index"
  StagingRotation.EquipmentEnable enaEquCoo(
    final staEqu=staEqu, final nEquAlt=nEquAlt)
    if have_chiWat
    "Compute enable command for equipment in cooling mode"
  StagingRotation.EquipmentAvailability avaEquHeaCoo[nHp](
    each final have_heaWat=have_heaWat,
    each final have_chiWat=have_chiWat,
    each final dtOff=dtOff)
    "Evaluate equipment availability in heating or cooling mode"
  Buildings.Controls.OBC.CDL.Logical.Pre y1HeaPre[nHp]
    if have_heaWat and have_chiWat
    "Left-limit of command signal to break algebraic loop"
  StagingRotation.SortRuntime sorRunTimCoo(
    final idxEquAlt=idxEquAlt,
    nin=nHp)
    if have_chiWat
    "Sort lead/lag alternate equipment by staging runtime – Cooling mode"
  Pumps.Generic.StagingHeadered staPumHeaWatPri(
    final is_pri=true,
    final is_ctlDp=have_pumPriCtlDp,
    final have_valInlIso=have_valHpInlIso,
    final have_valOutIso=have_valHpOutIso,
    final nEqu=nHp,
    final nPum=nPumHeaWatPri,
    final is_hdr=have_pumPriHdr,
    final dtRun=dtRunPumSta,
    final dVOffUp=dVOffUpPumSta,
    final dVOffDow=dVOffDowPumSta,
    final nSenDp=if have_senDpHeaWatRemWir then nSenDpHeaWatRem else 1,
    final V_flow_nominal=VHeaWatPri_flow_nominal,
    final dtRunFaiSaf=dtRunFaiSafPumSta,
    final dtRunFaiSafLowY=dtRunFaiSafLowYPumSta,
    final dpOff=dpOffPumSta,
    final yUp=yUpPumSta,
    final yDow=yDowPumSta)
    if have_pumHeaWatPri
    "Primary HW pump staging"
  Pumps.Generic.StagingHeadered staPumChiWatPri(
    final is_pri=true,
    final is_ctlDp=have_pumPriCtlDp,
    final have_valInlIso=have_valHpInlIso,
    final have_valOutIso=have_valHpOutIso,
    final nEqu=nHp,
    final nPum=nPumChiWatPri,
    final is_hdr=have_pumPriHdr,
    final dtRun=dtRunPumSta,
    final dVOffUp=dVOffUpPumSta,
    final dVOffDow=dVOffDowPumSta,
    final nSenDp=if have_senDpChiWatRemWir then nSenDpChiWatRem else 1,
    final V_flow_nominal=VChiWatPri_flow_nominal,
    final dtRunFaiSaf=dtRunFaiSafPumSta,
    final dtRunFaiSafLowY=dtRunFaiSafLowYPumSta,
    final dpOff=dpOffPumSta,
    final yUp=yUpPumSta,
    final yDow=yDowPumSta)
    if have_pumChiWatPri
    "Primary CHW pump staging"
  Pumps.Generic.StagingHeadered staPumChiWatSec(
    final is_pri=false,
    final nEqu=nHp,
    final nPum=nPumChiWatSec,
    final is_hdr=have_pumSecHdr,
    final is_ctlDp=have_pumSecCtlDp,
    final nSenDp=if have_senDpChiWatRemWir then nSenDpChiWatRem else 1,
    final V_flow_nominal=VChiWatSec_flow_nominal,
    final dtRun=dtRunPumSta,
    final dtRunFaiSaf=dtRunFaiSafPumSta,
    final dtRunFaiSafLowY=dtRunFaiSafLowYPumSta,
    final dVOffUp=dVOffUpPumSta,
    final dVOffDow=dVOffDowPumSta,
    final dpOff=dpOffPumSta,
    final yUp=yUpPumSta,
    final yDow=yDowPumSta)
    if have_pumChiWatSec
    "Secondary CHW pump staging"
  Pumps.Generic.StagingHeadered staPumHeaWatSec(
    final is_pri=false,
    final nEqu=nHp,
    final nPum=nPumHeaWatSec,
    final is_hdr=have_pumSecHdr,
    final is_ctlDp=have_pumSecCtlDp,
    final nSenDp=if have_senDpHeaWatRemWir then nSenDpHeaWatRem else 1,
    final V_flow_nominal=VHeaWatSec_flow_nominal,
    final dtRun=dtRunPumSta,
    final dtRunFaiSaf=dtRunFaiSafPumSta,
    final dtRunFaiSafLowY=dtRunFaiSafLowYPumSta,
    final dVOffUp=dVOffUpPumSta,
    final dVOffDow=dVOffDowPumSta,
    final dpOff=dpOffPumSta,
    final yUp=yUpPumSta,
    final yDow=yDowPumSta)
    if have_pumHeaWatSec
    "Secondary HW pump staging"
  Utilities.PlaceholderReal THeaWatRet(final have_inp=have_senTHeaWatPriRet,
      final have_inpPh=true)
                       if have_heaWat "Select HW return temperature sensor"
  Utilities.PlaceholderReal VHeaWatSta_flow(final have_inp=have_senVHeaWatPri,
      final have_inpPh=true) if have_heaWat
    "For staging logic select primary flow sensor if both primary and secondary sensors available"
  Utilities.PlaceholderReal TChiWatRet(final have_inp=have_senTChiWatPriRet,
      final have_inpPh=true)
                       if have_chiWat "Select CHW return temperature sensor"
  Utilities.PlaceholderReal VChiWatSta_flow(final have_inp=have_senVChiWatPri,
      final have_inpPh=true) if have_chiWat
    "For staging logic select primary flow sensor if both primary and secondary sensors available"
  Buildings.Controls.OBC.CDL.Logical.Pre y1HpPre[nHp]
    "Left-limit of command signal to break algebraic loop"
  StagingRotation.StageCompletion comStaCoo(
    nin=nHp)
    if have_chiWat
    "Check successful completion of cooling stage change"
  StagingRotation.StageCompletion comStaHea(
    nin=nHp)
    if have_heaWat
    "Check successful completion of heating stage change"
  Setpoints.PlantReset resHeaWat(
    final TSup_nominal=THeaWatSup_nominal,
    final TSupSetLim=THeaWatSupSet_min,
    final dpSet_max=dpHeaWatRemSet_max,
    final dpSet_min=dpHeaWatRemSet_min,
    final dtDel=dtDel,
    final dtHol=dtHol,
    final dtRes=dtResHeaWat,
    final nReqResIgn=nReqResIgnHeaWat,
    final nSenDpRem=nSenDpHeaWatRem,
    final resDp_max=resDpHeaWat_max,
    final resTSup_min=resTHeaWatSup_min,
    final res_init=res_init,
    final res_max=res_max,
    final res_min=res_min,
    final rsp=rspHeaWat,
    final rsp_max=rspHeaWat_max,
    final tri=triHeaWat) if have_heaWat "HW plant reset"
  Setpoints.PlantReset resChiWat(
    final TSup_nominal=TChiWatSup_nominal,
    final TSupSetLim=TChiWatSupSet_max,
    final dpSet_max=dpChiWatRemSet_max,
    final dpSet_min=dpChiWatRemSet_min,
    final dtDel=dtDel,
    final dtHol=dtHol,
    final dtRes=dtResChiWat,
    final nReqResIgn=nReqResIgnChiWat,
    final nSenDpRem=nSenDpChiWatRem,
    final resDp_max=resDpChiWat_max,
    final resTSup_min=resTChiWatSup_min,
    final res_init=res_init,
    final res_max=res_max,
    final res_min=res_min,
    final rsp=rspChiWat,
    final rsp_max=rspChiWat_max,
    final tri=triChiWat) if have_chiWat "CHW plant reset"
  Pumps.Primary.VariableSpeed ctlPumPri(
    final have_heaWat=have_heaWat,
    final have_chiWat=have_chiWat,
    final have_pumPriCtlDp=have_pumPriCtlDp,
    final have_pumChiWatPriDed=have_pumChiWatPriDed,
    final have_pumPriHdr=have_pumPriHdr,
    final nEqu=nHp,
    final nPumHeaWatPri=nPumHeaWatPri,
    final nPumChiWatPri=nPumChiWatPri,
    final yPumHeaWatPriSet=yPumHeaWatPriSet,
    final yPumChiWatPriSet=yPumChiWatPriSet,
    final have_senDpChiWatRemWir=have_senDpChiWatRemWir,
    final have_senDpHeaWatRemWir=have_senDpHeaWatRemWir,
    final kCtlDpChiWat=kCtlDpChiWat,
    final kCtlDpHeaWat=kCtlDpHeaWat,
    final nSenDpChiWatRem=nSenDpChiWatRem,
    final nSenDpHeaWatRem=nSenDpHeaWatRem,
    final TiCtlDpChiWat=TiCtlDpChiWat,
    final TiCtlDpHeaWat=TiCtlDpHeaWat,
    final yPumChiWatPri_min=yPumChiWatPri_min,
    final yPumHeaWatPri_min=yPumHeaWatPri_min)
    if have_pumHeaWatPriVar or have_pumChiWatPriVar
    "Primary pump speed control"
  Pumps.Generic.ControlDifferentialPressure ctlPumHeaWatSec(
    final have_senDpRemWir=have_senDpHeaWatRemWir,
    final nPum=nPumHeaWatSec,
    final nSenDpRem=nSenDpHeaWatRem,
    final y_min=yPumHeaWatSec_min,
    final k=kCtlDpHeaWat,
    final Ti=TiCtlDpHeaWat) if have_pumHeaWatSec and have_pumSecCtlDp
    "Secondary HW pump speed control"
  Pumps.Generic.ControlDifferentialPressure ctlPumChiWatSec(
    final have_senDpRemWir=have_senDpChiWatRemWir,
    final nPum=nPumChiWatSec,
    final nSenDpRem=nSenDpChiWatRem,
    final y_min=yPumChiWatSec_min,
    final k=kCtlDpChiWat,
    final Ti=TiCtlDpChiWat) if have_pumChiWatSec and have_pumSecCtlDp
    "Secondary CHW pump speed control"
  Buildings.Controls.OBC.CDL.Reals.Switch swiTSupSet[nHp]
    if have_heaWat and have_chiWat
    "Select supply temperature setpoint based on operating mode"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator repTChiWatSupSet(final
      nout=nHp) if have_chiWat "Replicate CHWST setpoint"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator repTHeaWatSupSet(final
      nout=nHp) if have_heaWat "Replicate HWST setpoint"
  Buildings.Controls.OBC.CDL.Routing.RealExtractSignal pasTHeaWatSupSet(final nin
      =nHp,                                                             final
      nout=nHp) if have_heaWat and not have_chiWat
    "Direct pass through for HWST setpoint"
  Buildings.Controls.OBC.CDL.Routing.RealExtractSignal pasTChiWatSupSet(final nin
      =nHp, final nout=nHp) if have_chiWat and not have_heaWat
    "Direct pass through for CHWST setpoint"
  HeatRecoveryChillers.Controller hrc(
    final COPHea_nominal=COPHeaHrc_nominal,
    final TChiWatSup_min=TChiWatSupHrc_min,
    final THeaWatSup_max=THeaWatSupHrc_max,
    final capCoo_min=capCooHrc_min,
    final capHea_min=capHeaHrc_min,
    final cp_default=cp_default,
    final dtLoa=dtLoaHrc,
    final dtRun=dtRunEna,
    final dtTem1=dtTem1Hrc,
    final dtTem2=dtTem2Hrc,
    final have_reqFlo=have_reqFloHrc,
    final rho_default=rho_default) if have_hrc
    "Sidestream heat recovery chiller control"
  Buildings.Controls.OBC.CDL.Routing.RealExtractSignal pasDpHeaWatRemSet(final
      nin=nSenDpHeaWatRem, final nout=nSenDpHeaWatRem)
    if have_heaWat and have_senDpHeaWatRemWir
    "Direct pass through for HW ∆p setpoint"
  Buildings.Controls.OBC.CDL.Routing.RealExtractSignal pasDpChiWatRemSet(final
      nin=nSenDpChiWatRem, final nout=nSenDpChiWatRem)
    if have_chiWat and have_senDpChiWatRemWir
    "Direct pass through for CHW ∆p setpoint"
  MinimumFlow.ControllerDualMode ctlFloMin(
    final have_chiWat=have_chiWat,
    final have_heaWat=have_heaWat,
    final have_pumChiWatPri=have_pumChiWatPri,
    final have_valInlIso=have_valHpInlIso,
    final have_valOutIso=have_valHpOutIso,
    final k=kValMinByp,
    final nEnaChiWat=if have_valHpInlIso or have_valHpOutIso then nHp
      elseif have_pumChiWatPri then nPumChiWatPri else nPumHeaWatPri,
    final nEnaHeaWat=if have_valHpInlIso or have_valHpOutIso then nHp else nPumHeaWatPri,
    final nEqu=nHp,
    final Ti=TiValMinByp,
    final VChiWat_flow_min=VChiWatHp_flow_min,
    final VChiWat_flow_nominal=VChiWatHp_flow_nominal,
    final VHeaWat_flow_min=VHeaWatHp_flow_min,
    final VHeaWat_flow_nominal=VHeaWatHp_flow_nominal) if is_priOnl
    "CHW/HW minimum flow bypass valve controller"
  Utilities.PlaceholderReal VHeaWatLoa_flow(final have_inp=is_priOnl, final
      have_inpPh=true) if have_heaWat
    "For HRC logic select either primary or secondary sensor depending on plant configuration"
  Utilities.PlaceholderReal VChiWatLoa_flow(final have_inp=is_priOnl, final
      have_inpPh=true) if have_chiWat
    "For HRC logic select either primary or secondary sensor depending on plant configuration"
equation
  connect(u1SchHea, enaHea.u1Sch)
  connect(nReqPlaHeaWat, enaHea.nReqPla)
  connect(TOut, enaHea.TOut)
  connect(enaHea.y1, idxStaHea.u1Lea)
  connect(avaStaHea.y1, idxStaHea.u1AvaSta)
  connect(idxStaHea.y, enaEquHea.uSta)
  connect(seqEve.y1, y1Hp)
  connect(seqEve.y1Hea, y1HeaHp)
  connect(seqEve.y1ValHeaWatOutIso, y1ValHeaWatHpOutIso)
  connect(seqEve.y1ValHeaWatInlIso, y1ValHeaWatHpInlIso)
  connect(seqEve.y1ValChiWatInlIso, y1ValChiWatHpInlIso)
  connect(seqEve.y1ValChiWatOutIso, y1ValChiWatHpOutIso)
  connect(idxStaHea.y, chaStaHea.uSta)
  connect(chaStaHea.y1Dow, idxStaHea.u1Dow)
  connect(chaStaHea.y1Up, idxStaHea.u1Up)
  connect(avaStaHea.y1, chaStaHea.u1AvaSta)
  connect(sorRunTimHea.yIdx, enaEquHea.uIdxAltSor)
  connect(nReqPlaChiWat, enaCoo.nReqPla)
  connect(TOut, enaCoo.TOut)
  connect(u1SchCoo, enaCoo.u1Sch)
  connect(avaStaCoo.y1, chaStaCoo.u1AvaSta)
  connect(enaCoo.y1, idxStaCoo.u1Lea)
  connect(chaStaCoo.y1Up, idxStaCoo.u1Up)
  connect(chaStaCoo.y1Dow, idxStaCoo.u1Dow)
  connect(idxStaCoo.y, enaEquCoo.uSta)
  connect(enaEquHea.y1, seqEve.u1Hea)
  connect(enaEquCoo.y1, seqEve.u1Coo)
  connect(y1HeaHp, y1HeaPre.u)
  connect(y1HeaPre.y, avaEquHeaCoo.u1Hea)
  connect(avaEquHeaCoo.y1Hea, avaStaHea.u1Ava)
  connect(avaEquHeaCoo.y1Coo, avaStaCoo.u1Ava)
  connect(avaStaCoo.y1, idxStaCoo.u1AvaSta)
  connect(avaEquHeaCoo.y1Hea, enaEquHea.u1Ava)
  connect(avaEquHeaCoo.y1Coo, enaEquCoo.u1Ava)
  connect(sorRunTimCoo.yIdx, enaEquCoo.uIdxAltSor)
  connect(idxStaCoo.y, chaStaCoo.uSta)
  connect(avaEquHeaCoo.y1Hea, sorRunTimHea.u1Ava)
  connect(avaEquHeaCoo.y1Coo, sorRunTimCoo.u1Ava)
  connect(staPumChiWatPri.y1, y1PumChiWatPri)
  connect(staPumChiWatPri.y1_actual, seqEve.u1PumChiWatPri_actual)
  connect(seqEve.y1PumChiWatPri, staPumChiWatPri.u1Pum)
  connect(u1PumChiWatPri_actual, staPumChiWatPri.u1Pum_actual)
  connect(u1PumHeaWatPri_actual, staPumHeaWatPri.u1Pum_actual)
  connect(staPumHeaWatPri.y1_actual, seqEve.u1PumHeaWatPri_actual)
  connect(staPumHeaWatSec.y1, y1PumHeaWatSec)
  connect(staPumChiWatSec.y1, y1PumChiWatSec)
  connect(u1PumHeaWatSec_actual, staPumHeaWatSec.u1Pum_actual)
  connect(u1PumChiWatSec_actual, staPumChiWatSec.u1Pum_actual)
  connect(staPumHeaWatPri.y1, y1PumHeaWatPri)
  connect(staPumChiWatSec.y1_actual, seqEve.u1PumChiWatSec_actual)
  connect(seqEve.y1PumHeaWatPri, staPumHeaWatPri.u1Pum)
  connect(staPumHeaWatSec.y1_actual, seqEve.u1PumHeaWatSec_actual)
  connect(VHeaWatSec_flow, staPumHeaWatSec.V_flow)
  connect(VChiWatSec_flow, staPumChiWatSec.V_flow)
  connect(THeaWatPriRet, THeaWatRet.u)
  connect(THeaWatRet.y, chaStaHea.TRet)
  connect(THeaWatSecRet, THeaWatRet.uPh)
  connect(VHeaWatPri_flow, VHeaWatSta_flow.u)
  connect(VHeaWatSta_flow.y, chaStaHea.V_flow)
  connect(VHeaWatSec_flow, VHeaWatSta_flow.uPh)
  connect(TChiWatPriRet, TChiWatRet.u)
  connect(TChiWatRet.y, chaStaCoo.TRet)
  connect(TChiWatSecRet, TChiWatRet.uPh)
  connect(VChiWatPri_flow, VChiWatSta_flow.u)
  connect(VChiWatSta_flow.y, chaStaCoo.V_flow)
  connect(VChiWatSec_flow, VChiWatSta_flow.uPh)
  connect(enaHea.y1, staPumHeaWatSec.u1Pla)
  connect(enaCoo.y1, staPumChiWatSec.u1Pla)
  connect(seqEve.y1ValHeaWatInlIso, staPumHeaWatPri.u1ValInlIso)
  connect(seqEve.y1ValHeaWatOutIso, staPumHeaWatPri.u1ValOutIso)
  connect(seqEve.y1ValChiWatInlIso, staPumChiWatPri.u1ValInlIso)
  connect(seqEve.y1ValChiWatOutIso, staPumChiWatPri.u1ValOutIso)
  connect(u1Hp_actual, sorRunTimHea.u1Run)
  connect(u1Hp_actual, sorRunTimCoo.u1Run)
  connect(y1Hp, y1HpPre.u)
  connect(y1HpPre.y, avaEquHeaCoo.u1)
  connect(idxStaCoo.y, comStaCoo.uSta)
  connect(comStaCoo.y1, chaStaCoo.u1StaPro)
  connect(u1Hp_actual, comStaCoo.u1_actual)
  connect(y1HpPre.y, comStaCoo.u1)
  connect(idxStaHea.y, comStaHea.uSta)
  connect(u1Hp_actual, comStaHea.u1_actual)
  connect(y1HpPre.y, comStaHea.u1)
  connect(comStaHea.y1, chaStaHea.u1StaPro)
  connect(resHeaWat.dpSet, dpHeaWatRemSet)
  connect(resChiWat.dpSet, dpChiWatRemSet)
  connect(nReqResHeaWat,resHeaWat.nReqRes)
  connect(nReqResChiWat,resChiWat.nReqRes)
  connect(enaCoo.y1, resChiWat.u1Ena)
  connect(enaHea.y1, resHeaWat.u1Ena)
  connect(comStaHea.y1, resHeaWat.u1StaPro)
  connect(comStaCoo.y1, resChiWat.u1StaPro)
  connect(resChiWat.TSupSet, chaStaCoo.TSupSet)
  connect(resHeaWat.TSupSet, chaStaHea.TSupSet)
  connect(ctlPumPri.yPumHeaWatPriHdr, yPumHeaWatPriHdr)
  connect(ctlPumPri.yPumChiWatPriHdr, yPumChiWatPriHdr)
  connect(ctlPumPri.yPumHeaWatPriDed, yPumHeaWatPriDed)
  connect(ctlPumPri.yPumChiWatPriDed, yPumChiWatPriDed)
  connect(staPumHeaWatPri.y1, ctlPumPri.u1PumHeaWatPri)
  connect(staPumChiWatPri.y1, ctlPumPri.u1PumChiWatPri)
  connect(seqEve.y1Hea, ctlPumPri.u1Hea)
  connect(ctlPumHeaWatSec.y, yPumHeaWatSec)
  connect(ctlPumChiWatSec.y, yPumChiWatSec)
  connect(u1PumHeaWatSec_actual, ctlPumHeaWatSec.y1_actual)
  connect(u1PumChiWatSec_actual, ctlPumChiWatSec.y1_actual)
  connect(resChiWat.dpSet, ctlPumChiWatSec.dpRemSet)
  connect(dpHeaWatRem, ctlPumHeaWatSec.dpRem)
  connect(resHeaWat.dpSet, ctlPumHeaWatSec.dpRemSet)
  connect(dpHeaWatLoc, ctlPumHeaWatSec.dpLoc)
  connect(dpHeaWatLocSet, ctlPumHeaWatSec.dpLocSet)
  connect(dpChiWatRem, ctlPumChiWatSec.dpRem)
  connect(dpChiWatLocSet, ctlPumChiWatSec.dpLocSet)
  connect(dpChiWatLoc, ctlPumChiWatSec.dpLoc)
  connect(u1AvaHp.y, avaEquHeaCoo.u1Ava)
  connect(repTChiWatSupSet.y, swiTSupSet.u3)
  connect(repTHeaWatSupSet.y, swiTSupSet.u1)
  connect(resChiWat.TSupSet, repTChiWatSupSet.u)
  connect(resHeaWat.TSupSet, repTHeaWatSupSet.u)
  connect(seqEve.y1Hea, swiTSupSet.u2)
  connect(swiTSupSet.y, TSupSet)
  connect(pasTChiWatSupSet.y, TSupSet)
  connect(pasTHeaWatSupSet.y, TSupSet)
  connect(repTChiWatSupSet.y, pasTChiWatSupSet.u)
  connect(repTHeaWatSupSet.y, pasTHeaWatSupSet.u)
  connect(resChiWat.TSupSet, TChiWatSupSet)
  connect(resHeaWat.TSupSet, THeaWatSupSet)
  connect(hrc.y1, y1Hrc)
  connect(hrc.y1Coo, y1CooHrc)
  connect(hrc.TSupSet, TSupSetHrc)
  connect(hrc.y1PumChiWat, y1PumChiWatHrc)
  connect(hrc.y1PumHeaWat, y1PumHeaWatHrc)
  connect(TChiWatSupSet, hrc.TChiWatSupSet)
  connect(THeaWatSupSet, hrc.THeaWatSupSet)
  connect(enaCoo.y1, hrc.u1Coo)
  connect(enaHea.y1, hrc.u1Hea)
  connect(TChiWatRetUpsHrc, hrc.TChiWatRetUpsHrc)
  connect(THeaWatRetUpsHrc, hrc.THeaWatRetUpsHrc)
  connect(THeaWatSecRet, hrc.THeaWatHrcLvg)
  connect(TChiWatSecRet, hrc.TChiWatHrcLvg)
  connect(u1Hrc_actual, hrc.u1Hrc_actual)
  connect(u1ReqFloChiWat, hrc.u1ReqFloChiWat)
  connect(u1ReqFloConWat, hrc.u1ReqFloConWat)
  connect(TChiWatPriSup, chaStaCoo.TPriSup)
  connect(THeaWatSecSup, chaStaHea.TSecSup)
  connect(TChiWatSecSup, chaStaCoo.TSecSup)
  connect(THeaWatPriSup, chaStaHea.TPriSup)
  connect(ctlPumHeaWatSec.y, staPumHeaWatSec.y)
  connect(ctlPumChiWatSec.y, staPumChiWatSec.y)
  connect(ctlPumHeaWatSec.dpLocSetMax, staPumHeaWatSec.dpSet[1])
  connect(ctlPumChiWatSec.dpLocSetMax, staPumChiWatSec.dpSet[1])
  connect(dpHeaWatLoc, staPumHeaWatSec.dp[1])
  connect(dpChiWatLoc, staPumChiWatSec.dp[1])
  connect(dpChiWatRem, staPumChiWatSec.dp)
  connect(dpHeaWatRem, staPumHeaWatSec.dp)
  connect(resHeaWat.dpSet, pasDpHeaWatRemSet.u)
  connect(pasDpHeaWatRemSet.y, staPumHeaWatSec.dpSet)
  connect(pasDpChiWatRemSet.y, staPumChiWatSec.dpSet)
  connect(resChiWat.dpSet, pasDpChiWatRemSet.u)
  connect(resChiWat.dpSet, ctlPumPri.dpChiWatRemSet)
  connect(resHeaWat.dpSet, ctlPumPri.dpHeaWatRemSet)
  connect(dpHeaWatRem, ctlPumPri.dpHeaWatRem)
  connect(dpHeaWatLocSet, ctlPumPri.dpHeaWatLocSet)
  connect(dpHeaWatLoc, ctlPumPri.dpHeaWatLoc)
  connect(pasDpHeaWatRemSet.y, staPumHeaWatPri.dpSet)
  connect(pasDpChiWatRemSet.y, staPumChiWatPri.dpSet)
  connect(ctlPumPri.dpChiWatLocSetMax, staPumChiWatPri.dpSet[1])
  connect(ctlPumPri.dpHeaWatLocSetMax, staPumHeaWatPri.dpSet[1])
  connect(dpHeaWatRem, staPumHeaWatPri.dp)
  connect(dpChiWatRem, staPumChiWatPri.dp)
  connect(dpHeaWatLoc, staPumHeaWatPri.dp[1])
  connect(dpChiWatLoc, staPumChiWatPri.dp[1])
  connect(dpChiWatLoc, ctlPumPri.dpChiWatLoc)
  connect(VChiWatPri_flow, staPumChiWatPri.V_flow)
  connect(VHeaWatPri_flow, staPumHeaWatPri.V_flow)
  connect(u1PumHeaWatPri_actual, ctlPumPri.u1PumHeaWatPri_actual)
  connect(u1PumChiWatPri_actual, ctlPumPri.u1PumChiWatPri_actual)
  connect(dpChiWatRem, ctlPumPri.dpChiWatRem)
  connect(dpChiWatLocSet, ctlPumPri.dpChiWatLocSet)
  connect(ctlFloMin.yValHeaWatMinByp, yValHeaWatMinByp)
  connect(ctlFloMin.yValChiWatMinByp, yValChiWatMinByp)
  connect(y1Hp, ctlFloMin.u1Equ)
  connect(y1HeaHp, ctlFloMin.u1HeaEqu)
  connect(y1ValHeaWatHpInlIso, ctlFloMin.u1ValHeaWatInlIso)
  connect(y1ValHeaWatHpOutIso, ctlFloMin.u1ValHeaWatOutIso)
  connect(y1ValChiWatHpInlIso, ctlFloMin.u1ValChiWatInlIso)
  connect(y1ValChiWatHpOutIso, ctlFloMin.u1ValChiWatOutIso)
  connect(u1PumHeaWatPri_actual, ctlFloMin.u1PumHeaWatPri_actual)
  connect(u1PumChiWatPri_actual, ctlFloMin.u1PumChiWatPri_actual)
  connect(VHeaWatPri_flow, ctlFloMin.VHeaWatPri_flow)
  connect(VChiWatPri_flow, ctlFloMin.VChiWatPri_flow)
  connect(ctlPumPri.yPumHeaWatPriHdr, staPumHeaWatPri.y)
  connect(ctlPumPri.yPumChiWatPriHdr, staPumChiWatPri.y)
  connect(VHeaWatSec_flow, VHeaWatLoa_flow.uPh)
  connect(VHeaWatPri_flow, VHeaWatLoa_flow.u)
  connect(VChiWatSec_flow, VChiWatLoa_flow.uPh)
  connect(VChiWatPri_flow, VChiWatLoa_flow.u)
  connect(VChiWatLoa_flow.y, hrc.VChiWatLoa_flow)
  connect(VHeaWatLoa_flow.y, hrc.VHeaWatLoa_flow)
end AirToWater;


<html>
<p>
This package contains control sequences for heat pump plants.
</p>
</html>

within Buildings.Templates.Plants.Controls;
package HeatPumps
end HeatPumps;


W. This model validates

Buildings.Templates.Plants.Controls.HeatPumps.AirToWater
in a configuration with three equally sized lead/lag alternate
heat pumps and a sidestream heat recovery chiller.

within Buildings.Templates.Plants.Controls.HeatPumps.Validation;
model AirToWater
  final parameter Real capHea_nominal(
    final unit="W")=sum(ctl.capHeaHp_nominal)
    "Installed heating capacity"
  parameter Real THeaWatSup_nominal(
    unit="K",
    displayUnit="degC")=323.15
    "Design HW supply temperature"
  parameter Real THeaWatRet_nominal(
    unit="K",
    displayUnit="degC")=315.15
    "Design HW return temperature"
  parameter Real VHeaWat_flow_nominal(
    unit="m3/s")=capHea_nominal / abs(THeaWatSup_nominal - THeaWatRet_nominal) /
    ctl.cp_default / ctl.rho_default
    "Design HW volume flow rate"
  final parameter Real capCoo_nominal(
    final unit="W")=sum(ctl.capCooHp_nominal)
    "Installed cooling capacity"
  parameter Real TChiWatSup_nominal(
    unit="K",
    displayUnit="degC")=280.15
    "Design CHW supply temperature"
  parameter Real TChiWatRet_nominal(
    unit="K",
    displayUnit="degC")=285.15
    "Design CHW return temperature"
  parameter Real VChiWat_flow_nominal(
    unit="m3/s")=capCoo_nominal / abs(TChiWatSup_nominal - TChiWatRet_nominal) /
    ctl.cp_default / ctl.rho_default
    "Design CHW volume flow rate"
  Buildings.Templates.Plants.Controls.HeatPumps.AirToWater ctl(
    have_heaWat=true,
    have_chiWat=true,
    have_hrc_select=true,
    have_valHpInlIso=true,
    have_valHpOutIso=true,
    have_pumChiWatPriDed_select=true,
    have_pumPriHdr=false,
    is_priOnl=false,
    have_pumHeaWatPriVar_select=false,
    have_pumChiWatPriVar_select=false,
    have_senVHeaWatPri_select=false,
    have_senVChiWatPri_select=false,
    have_senTHeaWatPriRet_select=false,
    have_senTChiWatPriRet_select=false,
    nHp=3,
    have_senDpHeaWatRemWir=false,
    nSenDpHeaWatRem=1,
    have_senDpChiWatRemWir=false,
    nSenDpChiWatRem=1,
    final THeaWatSup_nominal=THeaWatSup_nominal,
    THeaWatSupSet_min=298.15,
    VHeaWatHp_flow_nominal=1.1 * fill(VHeaWat_flow_nominal / ctl.nHp, ctl.nHp),
    VHeaWatHp_flow_min=0.6 * ctl.VHeaWatHp_flow_nominal,
    final VHeaWatSec_flow_nominal=VHeaWat_flow_nominal,
    capHeaHp_nominal=fill(350E3, ctl.nHp),
    dpHeaWatRemSet_max={5E4},
    final TChiWatSup_nominal=TChiWatSup_nominal,
    TChiWatSupSet_max=288.15,
    VChiWatHp_flow_nominal=1.1 * fill(VChiWat_flow_nominal / ctl.nHp, ctl.nHp),
    VChiWatHp_flow_min=0.6 * ctl.VChiWatHp_flow_nominal,
    final VChiWatSec_flow_nominal=VChiWat_flow_nominal,
    capCooHp_nominal=fill(350E3, ctl.nHp),
    yPumHeaWatPriSet=0.8,
    yPumChiWatPriSet=0.7,
    dpChiWatRemSet_max={5E4},
    staEqu=[
      1 / 3, 1 / 3, 1 / 3;
      2 / 3, 2 / 3, 2 / 3;
      1, 1, 1],
    idxEquAlt={1, 2, 3},
    TChiWatSupHrc_min=277.15,
    THeaWatSupHrc_max=333.15,
    COPHeaHrc_nominal=2.8,
    capCooHrc_min=ctl.capHeaHrc_min *(1 - 1 / ctl.COPHeaHrc_nominal),
    capHeaHrc_min=0.3 * 0.5 * sum(ctl.capHeaHp_nominal))
    "Plant controller"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable ratV_flow(
    table=[
      0, 0, 0;
      5, 0, 0;
      6, 1, 0;
      12, 0.2, 0.2;
      15, 0, 1;
      22, 0.1, 0.1;
      24, 0, 0],
    timeScale=3600)
    "Source signal for volume flow rate ratio – Index 1 for HW, 2 for CHW"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dTHeaWat(
    final k=(THeaWatRet_nominal - THeaWatSup_nominal) *(if ctl.have_hrc then 0.5
      else 1))
    "HW Delta-T"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dTChiWat(
    final k=(TChiWatRet_nominal - TChiWatSup_nominal) *(if ctl.have_hrc then 0.5
      else 1))
    "CHW Delta-T"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter VHeaWat_flow(
    final k=VHeaWat_flow_nominal)
    "Scale by design flow"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter VChiWat_flow(
    final k=VChiWat_flow_nominal)
    "Scale by design flow"
  Components.Controls.StatusEmulator y1Hp_actual[ctl.nHp]
    "HP status"
  Components.Controls.StatusEmulator y1PumHeaWatPri_actual1[ctl.nPumHeaWatPri]
    if ctl.have_heaWat and ctl.have_pumHeaWatPri
    "Primary HW pump status"
  Components.Controls.StatusEmulator y1PumChiWatPri_actual[ctl.nPumChiWatPri]
    if ctl.have_chiWat and ctl.have_pumChiWatPri
    "Primary CHW pump status"
  Components.Controls.StatusEmulator y1PumHeaWatSec_actual[ctl.nPumHeaWatSec]
    if ctl.have_heaWat and ctl.have_pumHeaWatSec
    "Secondary HW pump status"
  Components.Controls.StatusEmulator y1PumChiWatSec_actual[ctl.nPumChiWatSec]
    if ctl.have_chiWat and ctl.have_pumChiWatSec
    "Secondary CHW pump status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin TOut(
    amplitude=10,
    freqHz=0.5 / 24 / 3600,
    phase=- 0.43633231299858,
    offset=10 + 273.15)
    "OAT"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold isDemHea(
    t=1E-2,
    h=0.5E-2)
    "Return true if heating demand"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold isDemCoo(
    t=1E-2,
    h=0.5E-2)
    "Return true if cooling demand"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger reqPlaHeaWat
    "Generate HW plant request"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger reqPlaChiWat
    "Generate CHW plant request"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai[2](
    each k=5)
    "Use fraction of flow rate as a proxy for plant reset request"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reqResHeaWat
    "Generate HW reset request"
  Buildings.Controls.OBC.CDL.Conversions.RealToInteger reqResChiWat
    "Generate CHW reset request"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin sin[1](
    amplitude=0.1 * ctl.dpHeaWatRemSet_max,
    freqHz={4 / 8000},
    each phase=3.1415926535898)
    if ctl.have_heaWat
    "Source signal used to generate measurement values"
  Buildings.Controls.OBC.CDL.Reals.Add dpHeaWatRem[1]
    if ctl.have_heaWat
    "Differential pressure at remote location"
  Buildings.Controls.OBC.CDL.Reals.Add dpChiWatRem[1]
    if ctl.have_chiWat
    "Differential pressure at remote location"
  Pumps.Generic.ResetLocalDifferentialPressure resDpHeaWatLoc[1](
    each dpLocSet_max=20E4)
    if ctl.have_heaWat
    "Local HW DP reset"
  Pumps.Generic.ResetLocalDifferentialPressure resDpChiWatLoc[1](
    each dpLocSet_max=15E4)
    if ctl.have_chiWat
    "Local CHW DP reset"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin sin1[1](
    amplitude=0.1 * ctl.dpChiWatRemSet_max,
    freqHz={3 / 8000},
    each phase=3.1415926535898)
    "Source signal used to generate measurement values"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter dpHeaWatLoc(
    final k=4)
    if ctl.have_heaWat
    "Differential pressure local to the plant"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter dpChiWatLoc(
    final k=3)
    if ctl.have_chiWat
    "Differential pressure local to the plant"
  Components.Controls.StatusEmulator y1Hrc_actual
    if ctl.have_hrc
    "Sidestream HRC status"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dTHeaWatUpsHrc(
    final k=THeaWatRet_nominal - THeaWatSup_nominal)
    "HW Delta-T as measured upstream of HRC"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dTChiWatUpsHrc(
    final k=TChiWatRet_nominal - TChiWatSup_nominal)
    "CHW Delta-T as measured upstream of HRC"
  Buildings.Controls.OBC.CDL.Reals.Add THeaWatRet
    if ctl.have_heaWat
    "HWRT"
  Buildings.Controls.OBC.CDL.Reals.Add THeaWatRetUpsHrc
    if ctl.have_heaWat
    "HWRT upstream of HRC"
  Buildings.Controls.OBC.CDL.Reals.Add TChiWatRet
    if ctl.have_chiWat
    "CHWRT"
  Buildings.Controls.OBC.CDL.Reals.Add TChiWatRetUpsHrc
    if ctl.have_chiWat
    "CHWRT upstream of HRC"
equation
  connect(ratV_flow.y[1], VHeaWat_flow.u)
  connect(ratV_flow.y[2], VChiWat_flow.u)
  connect(ctl.y1Hp, y1Hp_actual.y1)
  connect(y1Hp_actual.y1_actual, ctl.u1Hp_actual)
  connect(ctl.y1PumHeaWatPri, y1PumHeaWatPri_actual1.y1)
  connect(ctl.y1PumChiWatPri, y1PumChiWatPri_actual.y1)
  connect(ctl.y1PumHeaWatSec, y1PumHeaWatSec_actual.y1)
  connect(ctl.y1PumChiWatSec, y1PumChiWatSec_actual.y1)
  connect(y1PumHeaWatPri_actual1.y1_actual, ctl.u1PumHeaWatPri_actual)
  connect(y1PumHeaWatSec_actual.y1_actual, ctl.u1PumHeaWatSec_actual)
  connect(y1PumChiWatPri_actual.y1_actual, ctl.u1PumChiWatPri_actual)
  connect(y1PumChiWatSec_actual.y1_actual, ctl.u1PumChiWatSec_actual)
  connect(TOut.y, ctl.TOut)
  connect(ratV_flow.y[1], isDemHea.u)
  connect(ratV_flow.y[2], isDemCoo.u)
  connect(isDemCoo.y, reqPlaChiWat.u)
  connect(isDemHea.y, reqPlaHeaWat.u)
  connect(reqPlaHeaWat.y, ctl.nReqPlaHeaWat)
  connect(reqPlaChiWat.y, ctl.nReqPlaChiWat)
  connect(VHeaWat_flow.y, ctl.VHeaWatPri_flow)
  connect(VHeaWat_flow.y, ctl.VHeaWatSec_flow)
  connect(VChiWat_flow.y, ctl.VChiWatPri_flow)
  connect(VChiWat_flow.y, ctl.VChiWatSec_flow)
  connect(ratV_flow.y, gai.u)
  connect(gai[1].y, reqResHeaWat.u)
  connect(gai[2].y, reqResChiWat.u)
  connect(reqResHeaWat.y, ctl.nReqResHeaWat)
  connect(reqResChiWat.y, ctl.nReqResChiWat)
  connect(sin.y, dpHeaWatRem.u2)
  connect(dpChiWatRem.y, ctl.dpChiWatRem)
  connect(dpHeaWatRem.y, ctl.dpHeaWatRem)
  connect(ctl.dpHeaWatRemSet, dpHeaWatRem.u1)
  connect(ctl.dpChiWatRemSet, dpChiWatRem.u1)
  connect(sin1.y, dpChiWatRem.u2)
  connect(dpHeaWatRem[1].y, dpHeaWatLoc.u)
  connect(ctl.dpHeaWatRemSet, resDpHeaWatLoc.dpRemSet)
  connect(dpChiWatRem[1].y, dpChiWatLoc.u)
  connect(ctl.dpChiWatRemSet, resDpChiWatLoc.dpRemSet)
  connect(dpHeaWatRem.y, resDpHeaWatLoc.dpRem)
  connect(dpChiWatRem.y, resDpChiWatLoc.dpRem)
  connect(resDpChiWatLoc.dpLocSet, ctl.dpChiWatLocSet)
  connect(dpChiWatLoc.y, ctl.dpChiWatLoc)
  connect(dpHeaWatLoc.y, ctl.dpHeaWatLoc)
  connect(resDpHeaWatLoc.dpLocSet, ctl.dpHeaWatLocSet)
  connect(ctl.y1Hrc, y1Hrc_actual.y1)
  connect(y1Hrc_actual.y1_actual, ctl.u1Hrc_actual)
  connect(ctl.TChiWatSupSet, ctl.TChiWatSecSup)
  connect(ctl.TChiWatSupSet, ctl.TChiWatPriSup)
  connect(ctl.THeaWatSupSet, ctl.THeaWatPriSup)
  connect(ctl.THeaWatSupSet, ctl.THeaWatSecSup)
  connect(ctl.THeaWatSupSet, THeaWatRet.u1)
  connect(dTHeaWat.y, THeaWatRet.u2)
  connect(ctl.TChiWatSupSet, TChiWatRet.u2)
  connect(dTChiWat.y, TChiWatRet.u1)
  connect(dTChiWatUpsHrc.y, TChiWatRetUpsHrc.u1)
  connect(TChiWatRetUpsHrc.u2, ctl.TChiWatSupSet)
  connect(THeaWatRetUpsHrc.u2, ctl.THeaWatSupSet)
  connect(dTHeaWatUpsHrc.y, THeaWatRetUpsHrc.u1)
  connect(THeaWatRet.y, ctl.THeaWatPriRet)
  connect(THeaWatRet.y, ctl.THeaWatSecRet)
  connect(TChiWatRet.y, ctl.TChiWatSecRet)
  connect(TChiWatRet.y, ctl.TChiWatPriRet)
  connect(TChiWatRetUpsHrc.y, ctl.TChiWatRetUpsHrc)
  connect(THeaWatRetUpsHrc.y, ctl.THeaWatRetUpsHrc)
end AirToWater;


Collection of validation models

within Buildings.Templates.Plants.Controls.HeatPumps;
package Validation
  "Collection of validation models"
end Validation;


Sidestream heat recovery chiller controller. The control sequence consists of the following parts.

within Buildings.Templates.Plants.Controls.HeatRecoveryChillers;
block Controller
  "Sidestream heat recovery chiller controller"
  parameter Boolean have_reqFlo=false
    "Set to true if HRC provides flow request point via network interface"
  parameter Real TChiWatSup_min(
    min=273.15,
    start=4 + 273.15,
    unit="K",
    displayUnit="degC")
    "Minimum allowable CHW supply temperature"
  parameter Real THeaWatSup_max(
    min=273.15,
    start=60 + 273.15,
    unit="K",
    displayUnit="degC")
    "Maximum allowable HW supply temperature"
  parameter Real COPHea_nominal(
    min=1.1,
    unit="1")
    "Heating COP at design heating conditions"
  parameter Real capCoo_min(
    min=0,
    unit="W")
    "Minimum cooling capacity below which cycling occurs"
  parameter Real capHea_min(
    min=0,
    unit="W")
    "Minimum heating capacity below which cycling occurs"
  parameter Real cp_default(
    min=0,
    unit="J/(kg.K)")
    "Default specific heat capacity used to compute required capacity";
  parameter Real rho_default(
    min=0,
    unit="kg/m3")
    "Default fluid density used to compute required capacity";
  parameter Real dtMea(
    min=0,
    unit="s")=300
    "Duration used to compute the moving average of required capacity";
  parameter Real dtRun(
    min=0,
    unit="s")=15 * 60
    "Minimum runtime of enable and disable states";
  parameter Real dtLoa(
    min=0,
    unit="s")=10 * 60
    "Runtime with sufficient load before enabling";
  parameter Real dtTem1(
    min=0,
    unit="s")=3 * 60
    "Runtime with first temperature threshold exceeded before disabling";
  parameter Real dtTem2(
    min=0,
    unit="s")=1 * 60
    "Runtime with second temperature threshold exceeded before disabling";
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatRetUpsHrc(
    final unit="K",
    displayUnit="degC")
    "CHW return temperature upstream of HRC"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet(
    final unit="K",
    displayUnit="degC")
    "Active CHW supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VChiWatLoa_flow(
    final unit="m3/s")
    "CHW volume flow rate distributed to the loads"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatRetUpsHrc(
    final unit="K",
    displayUnit="degC")
    "HW return temperature upstream of HRC"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatSupSet(
    final unit="K",
    displayUnit="degC")
    "Active HW supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VHeaWatLoa_flow(
    final unit="m3/s")
    "HW volume flow rate distributed to the loads"
  StagingRotation.LoadAverage loaChiWat(
    final typ=Buildings.Templates.Plants.Controls.Types.Application.Cooling,
    final cp_default=cp_default,
    final rho_default=rho_default,
    final dtMea=dtMea)
    "CHW load"
  StagingRotation.LoadAverage loaHeaWat(
    final typ=Buildings.Templates.Plants.Controls.Types.Application.Heating,
    final cp_default=cp_default,
    final rho_default=rho_default,
    final dtMea=dtMea)
    "HW load"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatHrcLvg(
    final unit="K",
    displayUnit="degC")
    "HRC leaving CHW temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatHrcLvg(
    final unit="K",
    displayUnit="degC")
    "HRC leaving HW temperature"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Coo
    "Cooling plant enable"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Hea
    "Heating plant enable"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Hrc_actual
    "HRC status"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1ReqFloChiWat
    if have_reqFlo
    "CHW flow request from HRC"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1ReqFloConWat
    if have_reqFlo
    "CW flow request from HRC"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1
    "Enable command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Coo
    "Mode command: true for cooling, false for heating"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumChiWat
    "HRC CHW pump enable command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1PumHeaWat
    "HRC HW pump enable command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TSupSet(
    final unit="K",
    displayUnit="degC")
    "Active supply temperature setpoint"
  Enable ena(
    final TChiWatSup_min=TChiWatSup_min,
    final THeaWatSup_max=THeaWatSup_max,
    final capCoo_min=capCoo_min,
    final capHea_min=capHea_min,
    final dtLoa=dtLoa,
    final dtRun=dtRun,
    final dtTem1=dtTem1,
    final dtTem2=dtTem2)
    "Compute enable command"
  ModeControl setMod(
    final COPHea_nominal=COPHea_nominal)
    "Set mode"
  Pumps.Primary.DisableDedicated pumChiWat(
    final have_reqFlo=have_reqFlo)
    "CHW pump control"
  Pumps.Primary.DisableDedicated pumHeaWat(
    final have_reqFlo=have_reqFlo)
    "HW pump control"
  Buildings.Controls.OBC.CDL.Logical.Pre preMod
    "Previous mode setting"
equation
  connect(TChiWatSupSet, loaChiWat.TSupSet)
  connect(TChiWatRetUpsHrc, loaChiWat.TRet)
  connect(VChiWatLoa_flow, loaChiWat.V_flow)
  connect(THeaWatSupSet, loaHeaWat.TSupSet)
  connect(THeaWatRetUpsHrc, loaHeaWat.TRet)
  connect(VHeaWatLoa_flow, loaHeaWat.V_flow)
  connect(u1Coo, ena.u1Coo)
  connect(u1Hea, ena.u1Hea)
  connect(u1Hrc_actual, ena.u1Hrc_actual)
  connect(loaChiWat.QReq_flow, ena.QChiWatReq_flow)
  connect(loaHeaWat.QReq_flow, ena.QHeaWatReq_flow)
  connect(TChiWatHrcLvg, ena.TChiWatHrcLvg)
  connect(THeaWatHrcLvg, ena.THeaWatHrcLvg)
  connect(loaChiWat.QReq_flow, setMod.QChiWatReq_flow)
  connect(loaHeaWat.QReq_flow, setMod.QHeaWatReq_flow)
  connect(TChiWatSupSet, setMod.TChiWatSupSet)
  connect(THeaWatSupSet, setMod.THeaWatSupSet)
  connect(setMod.y1Coo, y1Coo)
  connect(setMod.TSupSet, TSupSet)
  connect(ena.y1, y1)
  connect(ena.y1SetMod, setMod.u1SetMod)
  connect(ena.y1, pumChiWat.u1)
  connect(ena.y1, pumChiWat.u1Equ)
  connect(u1ReqFloChiWat, pumChiWat.u1ReqFlo)
  connect(u1Hrc_actual, pumChiWat.u1Equ_actual)
  connect(ena.y1, pumHeaWat.u1)
  connect(ena.y1, pumHeaWat.u1Equ)
  connect(u1ReqFloConWat, pumHeaWat.u1ReqFlo)
  connect(u1Hrc_actual, pumHeaWat.u1Equ_actual)
  connect(pumHeaWat.y1, y1PumHeaWat)
  connect(pumChiWat.y1, y1PumChiWat)
  connect(setMod.y1Coo, preMod.u)
  connect(preMod.y, ena.u1CooHrc)
end Controller;


Heat recovery chiller and HRC CHW and HW pumps enable. The available CHW load QChiWatReq_flow is calculated based on secondary
CHW temperature immediately upstream of the heat recovery chiller,
active CHW supply temperature setpoint and secondary CHW loop flow.

within Buildings.Templates.Plants.Controls.HeatRecoveryChillers;
block Enable
  "Heat recovery chiller and HRC CHW and HW pumps enable"
  parameter Real TChiWatSup_min(
    final min=273.15,
    start=4 + 273.15,
    final unit="K",
    displayUnit="degC")
    "Minimum allowable CHW supply temperature"
  parameter Real THeaWatSup_max(
    final min=273.15,
    start=60 + 273.15,
    final unit="K",
    displayUnit="degC")
    "Maximum allowable HW supply temperature"
  parameter Real capCoo_min(
    final min=0,
    final unit="W")
    "Minimum cooling capacity below which cycling occurs"
  parameter Real capHea_min(
    final min=0,
    final unit="W")
    "Minimum heating capacity below which cycling occurs"
  parameter Real dtRun(
    final min=0,
    final unit="s")=15 * 60
    "Minimum runtime of enable and disable states";
  parameter Real dtLoa(
    final min=0,
    final unit="s")=10 * 60
    "Runtime with sufficient load before enabling";
  parameter Real dtTem1(
    final min=0,
    final unit="s")=3 * 60
    "Runtime with first temperature threshold exceeded before disabling";
  parameter Real dtTem2(
    final min=0,
    final unit="s")=1 * 60
    "Runtime with second temperature threshold exceeded before disabling";
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Coo
    "Cooling plant enable"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Hea
    "Heating plant enable"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Hrc_actual
    "HRC status"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput QChiWatReq_flow(
    final unit="W")
    "CHW load"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput QHeaWatReq_flow(
    final unit="W")
    "HW load"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatHrcLvg(
    final unit="K",
    displayUnit="degC")
    "HRC leaving CHW temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatHrcLvg(
    final unit="K",
    displayUnit="degC")
    "HRC leaving HW temperature"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1CooHrc
    "HRC control mode command: true for cooling, false for heating"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1
    "Enable command"
  Buildings.Controls.OBC.CDL.Logical.Pre preEna
    "Left limit (in discrete-time) of enable signal"
  Buildings.Controls.OBC.CDL.Logical.Timer timCooEna(
    final t=dtRun)
    "Return true if cooling plant has been enabled for specified duration"
  Buildings.Controls.OBC.CDL.Logical.Not dis
    "Return true if disabled"
  Buildings.Controls.OBC.CDL.Logical.Timer runDis(
    final t=dtRun)
    "Return true if system has been disabled for specified duration"
  Buildings.Controls.OBC.CDL.Logical.Timer timHeaEna(
    final t=dtRun)
    "Return true if heating plant has been enabled for specified duration"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold higLoaCoo(
    final t=capCoo_min,
    h=1E-4 * capCoo_min)
    "Compare CHW load to cycling limit (hysteresis is to avoid chattering with some simulators)"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold higLoaHea(
    final t=capHea_min,
    h=1E-4 * capHea_min)
    "Compare HW load to cycling limit (hysteresis is to avoid chattering with some simulators)"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lowTChiWatLvg1(
    final t=TChiWatSup_min + 1)
    "Return true if first temperature limit exceeded"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold higTHeaWatLvg1(
    final t=THeaWatSup_max - 1.5)
    "Return true if first temperature limit exceeded"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold higTHeaWatLvg2(
    final t=THeaWatSup_max)
    "Return true if second temperature limit exceeded"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lowTChiWatLvg2(
    final t=TChiWatSup_min)
    "Return true if second temperature limit exceeded"
  Buildings.Controls.OBC.CDL.Logical.Timer timTHeaWatLvg1(
    final t=dtTem1)
    "Return true if threshold exceeded for specified duration"
  Buildings.Controls.OBC.CDL.Logical.Timer timTHeaWatLvg2(
    final t=dtTem2)
    "Return true if threshold exceeded for specified duration"
  Buildings.Controls.OBC.CDL.Logical.Timer timTChiWatLvg1(
    final t=dtTem1)
    "Return true if threshold exceeded for specified duration"
  Buildings.Controls.OBC.CDL.Logical.Timer timTChiWatLvg2(
    final t=dtTem2)
    "Return true if threshold exceeded for specified duration"
  Buildings.Controls.OBC.CDL.Logical.Timer timLoaCoo(
    final t=dtLoa)
    "Return true if threshold exceeded for specified duration"
  Buildings.Controls.OBC.CDL.Logical.Timer timLoaHea(
    final t=dtLoa)
    "Return true if threshold exceeded for specified duration"
  Buildings.Controls.OBC.CDL.Logical.MultiAnd allEna(
    nin=5)
    "All enable conditions met"
  Buildings.Controls.OBC.CDL.Logical.MultiOr anyDis(
    nin=5)
    "Any disable condition met"
  Buildings.Controls.OBC.CDL.Logical.Not disCoo
    "Return true if cooling plant disabled"
  Buildings.Controls.OBC.CDL.Logical.Not disHea
    "Return true if heating plant disabled"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lowLoaCoo(
    final t=capCoo_min,
    h=1E-4 * capCoo_min)
    "Compare CHW load to cycling limit (hysteresis is to avoid chattering with some simulators)"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold lowLoaHea(
    final t=capHea_min,
    h=1E-4 * capHea_min)
    "Compare HW load to cycling limit (hysteresis is to avoid chattering with some simulators)"
  Buildings.Controls.OBC.CDL.Logical.Or anyLowLoa
    "Any low load condition met"
  Buildings.Controls.OBC.CDL.Logical.FallingEdge off
    "Return true when HRC cycles off"
  Buildings.Controls.OBC.CDL.Logical.And anyLowLoaAndOff
    "Any low load condition met and HRC cycles off"
  Buildings.Controls.OBC.CDL.Logical.And enaAndCoo
    "HRC enabled in cooling mode"
  Buildings.Controls.OBC.CDL.Logical.And enaAndHea
    "HRC enabled in heating mode"
  Buildings.Controls.OBC.CDL.Logical.Not hea
    "True if heating control mode"
  Buildings.Controls.OBC.CDL.Logical.Or anyTChiWatLvg
    "Any leaving CHW temperature condition met"
  Buildings.Controls.OBC.CDL.Logical.Or anyTHeaWatLvg
    "Any leaving HW temperature condition met"
  Buildings.Controls.OBC.CDL.Logical.And anyTChiWatLvgAndHea
    "Any leaving CHW temperature condition met and HRC enabled in heating mode"
  Buildings.Controls.OBC.CDL.Logical.And anyTHeaWatLvgAndCoo
    "Any leaving HW temperature condition met and HRC enabled in cooling mode"
  Buildings.Controls.OBC.CDL.Logical.Latch enaDis
    "Maintain true signal until disable condition met"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1SetMod
    "Enable mode setting"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay truDel(
    delayTime=5)
    "Delay so that mode setting is enabled prior to enabling the HRC"
  Buildings.Controls.OBC.CDL.Logical.Edge edg
    "Enable mode setting just before enabling the HRC"
equation
  connect(preEna.y, dis.u)
  connect(dis.y, runDis.u)
  connect(u1Coo, timCooEna.u)
  connect(u1Hea, timHeaEna.u)
  connect(y1, preEna.u)
  connect(QChiWatReq_flow, higLoaCoo.u)
  connect(QHeaWatReq_flow, higLoaHea.u)
  connect(TChiWatHrcLvg, lowTChiWatLvg1.u)
  connect(THeaWatHrcLvg, higTHeaWatLvg1.u)
  connect(TChiWatHrcLvg, lowTChiWatLvg2.u)
  connect(THeaWatHrcLvg, higTHeaWatLvg2.u)
  connect(higTHeaWatLvg1.y, timTHeaWatLvg1.u)
  connect(higTHeaWatLvg2.y, timTHeaWatLvg2.u)
  connect(lowTChiWatLvg1.y, timTChiWatLvg1.u)
  connect(lowTChiWatLvg2.y, timTChiWatLvg2.u)
  connect(higLoaCoo.y, timLoaCoo.u)
  connect(higLoaHea.y, timLoaHea.u)
  connect(timCooEna.passed, allEna.u[1])
  connect(timHeaEna.passed, allEna.u[2])
  connect(runDis.passed, allEna.u[3])
  connect(timLoaCoo.passed, allEna.u[4])
  connect(timLoaHea.passed, allEna.u[5])
  connect(u1Coo, disCoo.u)
  connect(u1Hea, disHea.u)
  connect(disCoo.y, anyDis.u[1])
  connect(disHea.y, anyDis.u[2])
  connect(QChiWatReq_flow, lowLoaCoo.u)
  connect(QChiWatReq_flow, lowLoaHea.u)
  connect(lowLoaCoo.y, anyLowLoa.u1)
  connect(lowLoaHea.y, anyLowLoa.u2)
  connect(off.y, anyLowLoaAndOff.u1)
  connect(anyLowLoa.y, anyLowLoaAndOff.u2)
  connect(anyLowLoaAndOff.y, anyDis.u[3])
  connect(u1CooHrc, hea.u)
  connect(u1CooHrc, enaAndCoo.u2)
  connect(hea.y, enaAndHea.u2)
  connect(timTHeaWatLvg1.passed, anyTHeaWatLvg.u1)
  connect(timTChiWatLvg1.passed, anyTChiWatLvg.u1)
  connect(timTChiWatLvg2.passed, anyTChiWatLvg.u2)
  connect(timTHeaWatLvg2.passed, anyTHeaWatLvg.u2)
  connect(anyTChiWatLvg.y, anyTChiWatLvgAndHea.u2)
  connect(anyTChiWatLvgAndHea.y, anyDis.u[4])
  connect(anyTHeaWatLvgAndCoo.y, anyDis.u[5])
  connect(allEna.y, enaDis.u)
  connect(anyDis.y, enaDis.clr)
  connect(enaDis.y, truDel.u)
  connect(truDel.y, y1)
  connect(enaDis.y, edg.u)
  connect(edg.y, y1SetMod)
  connect(u1Hrc_actual, off.u)
  connect(preEna.y, enaAndCoo.u1)
  connect(preEna.y, enaAndHea.u1)
  connect(enaAndCoo.y, anyTHeaWatLvgAndCoo.u1)
  connect(anyTHeaWatLvg.y, anyTHeaWatLvgAndCoo.u2)
  connect(enaAndHea.y, anyTChiWatLvgAndHea.u1)
end Enable;


Mode control and setpoint selection.

within Buildings.Templates.Plants.Controls.HeatRecoveryChillers;
block ModeControl
  "Mode control and setpoint selection"
  parameter Real COPHea_nominal(
    final min=1.1,
    final unit="1")
    "Heating COP at design heating conditions"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1SetMod
    "Enable mode setting"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput QChiWatReq_flow(
    final unit="W")
    "CHW load"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput QHeaWatReq_flow(
    final unit="W")
    "HW load"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TChiWatSupSet(
    final unit="K",
    displayUnit="degC")
    "Active CHW supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput THeaWatSupSet(
    final unit="K",
    displayUnit="degC")
    "Active HW supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1Coo
    "Mode command: true for cooling, false for heating"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TSupSet(
    final unit="K",
    displayUnit="degC")
    "Active supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter QEvaHea_flow(
    final k=1 - 1 / COPHea_nominal)
    "Compute evaporator heat flow rate in heating mode"
  Buildings.Controls.OBC.CDL.Reals.Less les
    "True (cooling) if CHW load lower than evaporator heat flow rate in heating mode"
  Buildings.Controls.OBC.CDL.Reals.Switch selTSupSet
    "Select supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Logical.Switch setMod
    "Set mode if mode setting enabled, otherwise reuse previous mode"
  Buildings.Controls.OBC.CDL.Logical.Pre preMod
    "Previous mode setting"
equation
  connect(QHeaWatReq_flow, QEvaHea_flow.u)
  connect(QChiWatReq_flow, les.u1)
  connect(QEvaHea_flow.y, les.u2)
  connect(TChiWatSupSet, selTSupSet.u1)
  connect(THeaWatSupSet, selTSupSet.u3)
  connect(selTSupSet.y, TSupSet)
  connect(u1SetMod, setMod.u2)
  connect(setMod.y, y1Coo)
  connect(les.y, setMod.u1)
  connect(y1Coo, preMod.u)
  connect(preMod.y, setMod.u3)
  connect(y1Coo, selTSupSet.u2)
end ModeControl;


within Buildings.Templates.Plants.Controls;
package HeatRecoveryChillers
  "Package of sequences for heat recovery chillers"
end HeatRecoveryChillers;


Validation model for sidestream HRC enable and mode control. This model validates

Buildings.Templates.Plants.Controls.HeatRecoveryChillers.Enable
and

Buildings.Templates.Plants.Controls.HeatRecoveryChillers.ModeControl.
Consequently, it also validates

Buildings.Templates.Plants.Controls.HeatRecoveryChillers.Controller,
which is composed of the two former blocks.

within Buildings.Templates.Plants.Controls.HeatRecoveryChillers.Validation;
model EnableAndModeControl
  "Validation model for sidestream HRC enable and mode control"
  parameter Real cp_default(
    final min=0,
    final unit="J/(kg.K)")=4184
    "Default specific heat capacity used to compute required capacity";
  parameter Real rho_default(
    final min=0,
    final unit="kg/m3")=996
    "Default fluid density used to compute required capacity";
  parameter Real COPHea_nominal(
    final min=1.1,
    final unit="1")=2.8
    "Heating COP at design heating conditions"
  parameter Real capHea_nominal(
    final unit="W")=1E6
    "Installed heating capacity"
  parameter Real THeaWatSup_nominal(
    unit="K",
    displayUnit="degC")=323.15
    "Design HW supply temperature"
  parameter Real THeaWatRet_nominal(
    unit="K",
    displayUnit="degC")=315.15
    "Design HW return temperature"
  parameter Real VHeaWat_flow_nominal(
    unit="m3/s")=capHea_nominal / abs(THeaWatSup_nominal - THeaWatRet_nominal) /
    cp_default / rho_default
    "Design HW volume flow rate"
  final parameter Real capCoo_nominal(
    final unit="W")=capHea_nominal *(1 - 1 / COPHea_nominal)
    "Installed cooling capacity"
  parameter Real TChiWatSup_nominal(
    unit="K",
    displayUnit="degC")=280.15
    "Design CHW supply temperature"
  parameter Real TChiWatRet_nominal(
    unit="K",
    displayUnit="degC")=285.15
    "Design CHW return temperature"
  parameter Real VChiWat_flow_nominal(
    unit="m3/s")=capCoo_nominal / abs(TChiWatSup_nominal - TChiWatRet_nominal) /
    cp_default / rho_default
    "Design CHW volume flow rate"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable ratV_flow(
    table=[
      0, 0, 0;
      5, 0, 0;
      6, 1, 0;
      15, 0, 1;
      22, 0, 0.1;
      24, 0, 0],
    timeScale=3600)
    "Source signal for volume flow rate ratio – Index 1 for HW, 2 for CHW"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatRet(
    final k=THeaWatRet_nominal,
    y(
      final unit="K",
      displayUnit="degC"))
    "HWRT"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatRet(
    final k=TChiWatRet_nominal,
    y(
      final unit="K",
      displayUnit="degC"))
    "CHWRT"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter VHeaWat_flow(
    final k=VHeaWat_flow_nominal)
    "Scale by design flow"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter VChiWat_flow(
    final k=VChiWat_flow_nominal)
    "Scale by design flow"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSup(
    final k=THeaWatSup_nominal,
    y(
      final unit="K",
      displayUnit="degC"))
    "HWST"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSup(
    final k=TChiWatSup_nominal,
    y(
      final unit="K",
      displayUnit="degC"))
    "CHWST"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold u1Hea
    "Compute heating plant enable signal"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold u1Coo
    "Compute cooling plant enable signal"
  StagingRotation.LoadAverage loaChiWat(
    typ=Buildings.Templates.Plants.Controls.Types.Application.Cooling,
    final cp_default=cp_default,
    final rho_default=rho_default)
    "Available CHW load"
  Buildings.Templates.Plants.Controls.HeatRecoveryChillers.Enable ena(
    TChiWatSup_min=277.15,
    THeaWatSup_max=328.15,
    capCoo_min=0.3 * capCoo_nominal,
    capHea_min=0.3 * 0.3 * capHea_nominal)
  StagingRotation.LoadAverage loaHeaWat(
    typ=Buildings.Templates.Plants.Controls.Types.Application.Heating,
    final cp_default=cp_default,
    final rho_default=rho_default)
    "Available HW load"
  Components.Controls.StatusEmulator sta
    "Emulate HRC status"
  ModeControl setMod(
    COPHea_nominal=2.8)
    "Set mode"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin dTHeaWat(
    amplitude=THeaWatSup_nominal - THeaWatRet_nominal,
    freqHz=3 / 50000,
    offset=(THeaWatSup_nominal - THeaWatRet_nominal))
    "HW Delta_T across HRC condenser"
  Buildings.Controls.OBC.CDL.Reals.Add THeaWatHrcLvg
    "HRC leaving HWT"
  Buildings.Controls.OBC.CDL.Reals.Divide ratFlo
    "Flow ratio"
  Buildings.Controls.OBC.CDL.Reals.Multiply dTRatFlo
    "HW Delta-T times flow ratio"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter dTChiWat(
    k=-(1 - 1 / COPHea_nominal))
    "HRC leaving CHWT"
  Buildings.Controls.OBC.CDL.Logical.Pre preMod
    "Previous mode setting"
  Buildings.Controls.OBC.CDL.Reals.Max bou
    "Bound to avoid division by zero"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant cst(
    k=1E-4)
    "Constant"
  Buildings.Controls.OBC.CDL.Reals.Max bou1
    "Bound to avoid unrealistic values"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant cst1(
    k=3 + 273.15)
    "Constant"
  Buildings.Controls.OBC.CDL.Reals.Add TChiWatHrcLvg
    "HRC leaving CHWT"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal staToReal
    "Convert status to real"
  Buildings.Controls.OBC.CDL.Reals.Multiply dTEna
    "Non-zero HW Delta-T when HRC on"
  Buildings.Controls.OBC.CDL.Logical.MultiAnd mulAnd(
    nin=3)
    "Make status come and go at low load"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greLoaChiWat(
    final t=ena.capCoo_min)
    "True if load greater than minimum before cycling"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greLoaHeaWat(
    final t=ena.capHea_min)
    "True if load greater than minimum before cycling"
equation
  connect(ratV_flow.y[1], VHeaWat_flow.u)
  connect(ratV_flow.y[2], VChiWat_flow.u)
  connect(VHeaWat_flow.y, u1Hea.u)
  connect(VChiWat_flow.y, u1Coo.u)
  connect(TChiWatSup.y, loaChiWat.TSupSet)
  connect(TChiWatRet.y, loaChiWat.TRet)
  connect(THeaWatSup.y, loaHeaWat.TSupSet)
  connect(THeaWatRet.y, loaHeaWat.TRet)
  connect(VHeaWat_flow.y, loaHeaWat.V_flow)
  connect(loaChiWat.QReq_flow, ena.QChiWatReq_flow)
  connect(loaHeaWat.QReq_flow, ena.QHeaWatReq_flow)
  connect(VChiWat_flow.y, loaChiWat.V_flow)
  connect(u1Hea.y, ena.u1Hea)
  connect(u1Coo.y, ena.u1Coo)
  connect(ena.y1, sta.y1)
  connect(ena.y1SetMod, setMod.u1SetMod)
  connect(loaChiWat.QReq_flow, setMod.QChiWatReq_flow)
  connect(loaHeaWat.QReq_flow, setMod.QHeaWatReq_flow)
  connect(TChiWatSup.y, setMod.TChiWatSupSet)
  connect(THeaWatSup.y, setMod.THeaWatSupSet)
  connect(THeaWatRet.y, THeaWatHrcLvg.u2)
  connect(THeaWatHrcLvg.y, ena.THeaWatHrcLvg)
  connect(VHeaWat_flow.y, ratFlo.u1)
  connect(dTRatFlo.y, dTChiWat.u)
  connect(setMod.y1Coo, preMod.u)
  connect(preMod.y, ena.u1CooHrc)
  connect(VChiWat_flow.y, bou.u1)
  connect(cst.y, bou.u2)
  connect(bou.y, ratFlo.u2)
  connect(ratFlo.y, dTRatFlo.u2)
  connect(TChiWatRet.y, TChiWatHrcLvg.u2)
  connect(bou1.y, ena.TChiWatHrcLvg)
  connect(dTChiWat.y, TChiWatHrcLvg.u1)
  connect(dTHeaWat.y, dTEna.u2)
  connect(staToReal.y, dTEna.u1)
  connect(dTEna.y, THeaWatHrcLvg.u1)
  connect(dTEna.y, dTRatFlo.u1)
  connect(TChiWatHrcLvg.y, bou1.u1)
  connect(cst1.y, bou1.u2)
  connect(sta.y1_actual, mulAnd.u[1])
  connect(loaChiWat.QReq_flow, greLoaChiWat.u)
  connect(loaHeaWat.QReq_flow, greLoaHeaWat.u)
  connect(greLoaHeaWat.y, mulAnd.u[2])
  connect(greLoaChiWat.y, mulAnd.u[3])
  connect(mulAnd.y, ena.u1Hrc_actual)
  connect(mulAnd.y, staToReal.u)
end EnableAndModeControl;


Collection of validation models

within Buildings.Templates.Plants.Controls.HeatRecoveryChillers;
package Validation
  "Collection of validation models"
end Validation;


Minimum flow bypass valve controller. The minimum flow bypass valve is modulated based on a reverse acting control loop
to maintain the primary flow rate at setpoint.
The setpoint is calculated as described in

Buildings.Templates.Plants.Controls.MinimumFlow.Setpoint.

within Buildings.Templates.Plants.Controls.MinimumFlow;
block Controller
  "Minimum flow bypass valve controller"
  parameter Boolean have_valInlIso
    "Set to true to enable control loop based on inlet isolation valve command"
  parameter Boolean have_valOutIso
    "Set to true to enable control loop based on outlet isolation valve command"
  parameter Integer nEqu(
    final min=1)=0
    "Number of plant equipment"
  parameter Integer nEna(
    final min=1)=0
    "Number of enable signals – Valve command or pump status"
  parameter Real V_flow_nominal[:](
    each final unit="m3/s")
    "Design flow rate – Each unit";
  parameter Real V_flow_min[:](
    each final unit="m3/s")
    "Minimum flow rate – Each unit";
  parameter Real k(
    min=0)=1
    "Gain of controller";
  parameter Modelica.Units.SI.Time Ti(
    min=Buildings.Controls.OBC.CDL.Constants.small)=0.5
    "Time constant of integrator block";
  Buildings.Controls.OBC.CDL.Interfaces.RealInput VPri_flow(
    final unit="m3/s")
    "Primary volume flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1PumPri_actual[nEna]
    if not have_valInlIso and not have_valOutIso
    "Primary pump status"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1ValInlIso[nEna]
    if have_valInlIso
    "Inlet isolation valve command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1ValOutIso[nEna]
    if have_valOutIso
    "Outlet isolation valve command"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput y(
    final unit="1")
    "Valve command"
  Utilities.PIDWithEnable ctl(
    final k=k,
    final Ti=Ti,
    final reverseActing=true,
    y_reset=1,
    y_neutral=1)
    "PI controller"
  Buildings.Controls.OBC.CDL.Logical.MultiOr anyValInlIso(
    final nin=nEna)
    if have_valInlIso
    "True if any valve commanded open"
  Buildings.Controls.OBC.CDL.Logical.MultiOr anyValOutIso(
    final nin=nEna)
    if have_valOutIso
    "True if any valve commanded open"
  Buildings.Controls.OBC.CDL.Logical.MultiOr anyPumPri(
    final nin=nEna)
    if not have_valInlIso and not have_valOutIso
    "True if any pump proven on"
  Utilities.PlaceholderLogical phValInlIso(
    final have_inp=have_valInlIso,
    u_internal=false)
    "Placeholder signal"
  Utilities.PlaceholderLogical phValOutIso(
    final have_inp=have_valOutIso,
    u_internal=false)
    "Placeholder signal"
  Utilities.PlaceholderLogical phPrumPri(
    final have_inp=not have_valInlIso and not have_valOutIso,
    u_internal=false)
    "Placeholder signal"
  Buildings.Controls.OBC.CDL.Logical.MultiOr any(
    nin=3)
    "True if any enable condition met"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput u1Equ[nEqu]
    "Equipment enable command"
  Setpoint setFloMin(
    final V_flow_nominal=V_flow_nominal,
    final V_flow_min=V_flow_min,
    nEqu=nEqu)
    "Calculate minimum flow setpoint"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput VPriSet_flow(
    final unit="m3/s")
    "Primary flow setpoint"
equation
  connect(anyValInlIso.u, u1ValInlIso)
  connect(anyValOutIso.u, u1ValOutIso)
  connect(anyPumPri.u, u1PumPri_actual)
  connect(VPri_flow, ctl.u_m)
  connect(anyValInlIso.y, phValInlIso.u)
  connect(anyValOutIso.y, phValOutIso.u)
  connect(anyPumPri.y, phPrumPri.u)
  connect(phValInlIso.y, any.u[1])
  connect(phValOutIso.y, any.u[2])
  connect(phPrumPri.y, any.u[3])
  connect(any.y, ctl.uEna)
  connect(ctl.y, y)
  connect(u1Equ, setFloMin.u1)
  connect(setFloMin.VPriSet_flow, ctl.u_s)
  connect(setFloMin.VPriSet_flow, VPriSet_flow)
end Controller;