Validation model. Validation model for the block

Buildings.Templates.Plants.Controls.Utilities.PlaceholderLogical.

within Buildings.Templates.Plants.Controls.Utilities.Validation;
model PlaceholderLogical "Validation model"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderLogical
                                                                phPar(
    have_inp=false,
      have_inpPh=false,
    u_internal=false)                 "Placeholder parameter"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse pul(period=1)
    "Source signal for value to replace"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderLogical
                                                                phInp(have_inp=false,
      have_inpPh=true) "Placeholder signal"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant con(k=true) "Constant"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderLogical
                                                                phNo(
    have_inp=true,
    have_inpPh=false,
    u_internal=false)
                  "No placeholder: use input signal"
equation
  connect(pul.y, phPar.u)
  connect(pul.y, phInp.u)
  connect(pul.y, phNo.u)
  connect(con.y, phInp.uPh)
end PlaceholderLogical;


Validation model. Validation model for the block

Buildings.Templates.Plants.Controls.Utilities.PlaceholderReal.

within Buildings.Templates.Plants.Controls.Utilities.Validation;
model PlaceholderReal "Validation model"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderReal phPar(
    have_inp=false,
      have_inpPh=false, u_internal=1) "Placeholder parameter"
  Buildings.Controls.OBC.CDL.Reals.Sources.Pulse
                                               pul(period=1)
    "Source signal for value to replace"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderReal phInp(have_inp=false,
      have_inpPh=true) "Placeholder signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(k=2) "Constant"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderReal phNo(
    have_inp=true,
    have_inpPh=false,
    u_internal=1) "No placeholder: use input signal"
equation
  connect(pul.y, phNo.u)
  connect(pul.y, phPar.u)
  connect(pul.y, phInp.u)
  connect(con.y, phInp.uPh)
end PlaceholderReal;


Number of stages. Validation model for the block

Buildings.Templates.Plants.Controls.Utilities.StageIndex.

within Buildings.Templates.Plants.Controls.Utilities.Validation;
model StageIndex
  parameter Integer nSta=4
    "Number of stages"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse ena(
    width=0.9,
    period=160,
    shift=10)
    "Enable signal"
  Buildings.Templates.Plants.Controls.Utilities.StageIndex idxSta(
    have_inpAva=false,
    final nSta=nSta)
    "Compute stage index - No minimum runtime, all stages available"
  Buildings.Controls.OBC.CDL.Logical.Sources.SampleTrigger upPul(
    period=20)
    "Stage up command pulse"
  Buildings.Controls.OBC.CDL.Logical.Sources.SampleTrigger dowPul(
    period=20)
    "Stage down command pulse"
  Buildings.Templates.Plants.Controls.Utilities.StageIndex idxStaUna(
    final nSta=nSta)
    "Compute stage index - No minimum runtime, some unavailable stages"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant u1AvaSta[nSta](
    k={false, false, true, true})
    "Stage available signal"
  Buildings.Templates.Plants.Controls.Utilities.StageIndex idxStaRun(
    have_inpAva=false,
    final nSta=nSta,
    dtRun=25)
    "Compute stage index - Minimum runtime, all stages available"
  Buildings.Templates.Plants.Controls.Utilities.StageIndex idxStaRunUna(
    final nSta=nSta,
    dtRun=25)
    "Compute stage index - Minimum runtime, some unavailable stages"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable booTimTab(
    table=[
      0, 0, 0;
      10, 1, 0;
      70, 0, 1],
    period=160)
    "Signal to inhibit up and down commands"
  Buildings.Controls.OBC.CDL.Logical.And u1Up
    "Stage up command"
  Buildings.Controls.OBC.CDL.Logical.And u1Dow
    "Stage down command"
  Buildings.Controls.OBC.CDL.Logical.TrueFalseHold u1UpHol(final
      falseHoldDuration=0, trueHoldDuration=0.1)
    "Hold stage up command for plotting"
  Buildings.Controls.OBC.CDL.Logical.TrueFalseHold u1DowHol(final
      falseHoldDuration=0, trueHoldDuration=0.1)
    "Hold stage down command for plotting"
equation
  connect(ena.y, idxSta.u1Lea)
  connect(ena.y, idxStaUna.u1Lea)
  connect(ena.y, idxStaRun.u1Lea)
  connect(u1AvaSta.y, idxStaUna.u1AvaSta)
  connect(ena.y, idxStaRunUna.u1Lea)
  connect(u1AvaSta.y, idxStaRunUna.u1AvaSta)
  connect(upPul.y, u1Up.u2)
  connect(dowPul.y, u1Dow.u2)
  connect(booTimTab.y[2], u1Dow.u1)
  connect(u1Up.y, idxSta.u1Up)
  connect(u1Dow.y, idxSta.u1Dow)
  connect(u1Up.y, idxStaUna.u1Up)
  connect(u1Dow.y, idxStaUna.u1Dow)
  connect(u1Dow.y, idxStaRun.u1Dow)
  connect(u1Dow.y, idxStaRunUna.u1Dow)
  connect(u1Up.y, idxStaRun.u1Up)
  connect(u1Up.y, idxStaRunUna.u1Up)
  connect(booTimTab.y[1], u1Up.u1)
  connect(u1Up.y, u1UpHol.u)
  connect(u1Dow.y, u1DowHol.u)
end StageIndex;


Validation model for the Timer block. Validation model for the block

Buildings.Templates.Plants.Controls.Utilities.TimerWithReset.

within Buildings.Templates.Plants.Controls.Utilities.Validation;
model TimerWithReset
  "Validation model for the Timer block"
  Buildings.Templates.Plants.Controls.Utilities.TimerWithReset noThr
    "Timer that do not compare threshold – No Reset"
  Buildings.Templates.Plants.Controls.Utilities.TimerWithReset thrTim(
    final t=0.3) "Timer that compares threshold – No Reset"
  Buildings.Templates.Plants.Controls.Utilities.TimerWithReset thrTim1(
    final t=0.3) "Timer that compares threshold – No Reset"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul(
    final width=0.7,
    final period=2)
    "Block that outputs cyclic on and off"
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse booPul1(
    final width=0.7,
    final period=2,
    final shift=-1)
    "Block that outputs cyclic on and off"

  Buildings.Controls.OBC.CDL.Logical.Sources.Constant
                                                   con(k=false) "Constant"
  Buildings.Templates.Plants.Controls.Utilities.TimerWithReset noThrRes
    "Timer that do not compare threshold – With Reset"
  Buildings.Templates.Plants.Controls.Utilities.TimerWithReset thrTimRes(final t=
        0.3) "Timer that compares threshold – With Reset"
  Buildings.Templates.Plants.Controls.Utilities.TimerWithReset thrTim1Res(final t=
        0.3) "Timer that compares threshold – With Reset"
  Buildings.Controls.OBC.CDL.Logical.Sources.SampleTrigger
                                                   samTri(final period=1.5,
      shift=1.2) "Block that generates periodic reset signal"
  Buildings.Controls.OBC.CDL.Logical.TrueFalseHold res(trueHoldDuration=0.01,
      falseHoldDuration=0) "Hold signal for plotting"
equation
  connect(booPul.y,noThr.u)
  connect(booPul.y,thrTim.u)
  connect(booPul1.y,thrTim1.u)
  connect(con.y, noThr.reset)
  connect(con.y, thrTim.reset)
  connect(con.y, thrTim1.reset)
  connect(samTri.y, noThrRes.reset)
  connect(booPul.y, noThrRes.u)
  connect(booPul.y, thrTimRes.u)
  connect(samTri.y, thrTimRes.reset)
  connect(samTri.y, thrTim1Res.reset)
  connect(booPul1.y, thrTim1Res.u)
  connect(samTri.y, res.u)
end TimerWithReset;


Array with true elements and same size as input vector. Validation model for the block

Buildings.Templates.Plants.Controls.Utilities.TrueArrayConditional.

within Buildings.Templates.Plants.Controls.Utilities.Validation;
model TrueArrayConditional
  Buildings.Templates.Plants.Controls.Utilities.TrueArrayConditional truArrConSam(nin=2)
    "Array with true elements and same size as input vector"
  Buildings.Controls.OBC.CDL.Integers.Sources.Pulse uIdx1(
    amplitude=1,
    period=4,
    shift=1.5) "Source signal for index of first true element"
  Buildings.Controls.OBC.CDL.Integers.Sources.Pulse uIdx2(
    amplitude=1,
    period=2.5,
    offset=2) "Source signal for index of second true element"
  Buildings.Controls.OBC.CDL.Integers.Sources.TimeTable uTru(table=[0,0; 1,1; 2,
        2], period=4) "Source signal for number of true elements"
  Buildings.Templates.Plants.Controls.Utilities.TrueArrayConditional truArrConGre(nout=4,
      nin=2) "Array with true elements and size greater than input vector"
equation
  connect(uTru.y[1], truArrConSam.u)
  connect(uIdx1.y, truArrConSam.uIdx[1])
  connect(uTru.y[1], truArrConGre.u)
  connect(uIdx1.y, truArrConGre.uIdx[1])
  connect(uIdx2.y, truArrConSam.uIdx[2])
  connect(uIdx2.y, truArrConGre.uIdx[2])
end TrueArrayConditional;


Air-to-water heat pump plant

within Buildings.Templates.Plants.HeatPumps;
model AirToWater
  "Air-to-water heat pump plant"
  extends Buildings.Templates.Plants.HeatPumps.Interfaces.PartialHeatPumpPlant(
    redeclare final package MediumChiWat=MediumHeaWat,
    redeclare final package MediumSou=MediumAir,
    redeclare Buildings.Templates.Plants.HeatPumps.Components.Controls.AirToWater ctl(ctl(
      final yPumHeaWatPriSet=yPumHeaWatPriSet,
      final yPumChiWatPriSet=yPumChiWatPriSet)),
    final typ=Buildings.Templates.Components.Types.HeatPump.AirToWater,
    final is_rev=have_chiWat,
    final cfg(
      final typMod=hp.typMod));
  parameter Boolean is_dpBalYPumSetCal(start=false)=false
    "Set to true to automatically size balancing valves or evaluate pump speed providing design flow"
  // The check valve pressure drop is scaled for configurations with common dedicated CHW and HW pumps.
  final parameter Modelica.Units.SI.PressureDifference dpValCheHeaWat_nominal=
    dat.dpValCheHeaWat_nominal * (hp.mHeaWatHp_flow_nominal / max(dat.pumHeaWatPri.m_flow_nominal))^2
    "Primary HW pump check valve pressure drop at design HW flow rate";
  final parameter Modelica.Units.SI.PressureDifference dpValCheChiWat_nominal=
    if have_chiWat then (
    if typPumChiWatPri==Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.None
    then dat.dpValCheHeaWat_nominal * (hp.mChiWatHp_flow_nominal / max(dat.pumHeaWatPri.m_flow_nominal))^2
    else dat.dpValCheChiWat_nominal)
    else 0
    "Primary (CHW or common HW and CHW) pump check valve pressure drop at design CHW flow rate";
  final parameter Modelica.Units.SI.PressureDifference dpBalHeaWatHp_nominal=
    if is_dpBalYPumSetCal
      and typPumHeaWatPri==Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Constant
    then Buildings.Templates.Utilities.computeBalancingPressureDrop(
      m_flow_nominal=hp.mHeaWatHp_flow_nominal,
      dp_nominal=hp.dpHeaWatHp_nominal + max(valIso.dpValveHeaWat_nominal) * (
        (if have_valHpInlIso then 1 else 0) + (if have_valHpOutIso then 1 else 0))
        + dpValCheHeaWat_nominal,
      datPum=dat.pumHeaWatPriSin[1])
    else dat.dpBalHeaWatHp_nominal
    "HP HW balancing valve pressure drop at design HW flow";
  final parameter Modelica.Units.SI.PressureDifference dpBalChiWatHp_nominal=
    if is_dpBalYPumSetCal
      and (typPumChiWatPri==Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Constant
      or have_chiWat and not have_pumChiWatPriDed and
      typPumHeaWatPri==Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Constant)
    then Buildings.Templates.Utilities.computeBalancingPressureDrop(
      m_flow_nominal=hp.mChiWatHp_flow_nominal,
      dp_nominal=hp.dpChiWatHp_nominal + max(valIso.dpValveChiWat_nominal) * (
        (if have_valHpInlIso then 1 else 0) + (if have_valHpOutIso then 1 else 0))
        + dpValCheChiWat_nominal,
      datPum=if cfg.typPumChiWatPri==Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Constant
        then dat.pumChiWatPriSin[1] else dat.pumHeaWatPriSin[1])
    else dat.dpBalChiWatHp_nominal
    "HP CHW balancing valve pressure drop at design CHW flow";
  final parameter Real yPumHeaWatPriSet(
    final fixed=false,
    final max=2,
    final min=0,
    start=1,
    final unit="1")
    "Primary pump speed providing design heat pump flow in heating mode"
  final parameter Real yPumChiWatPriSet(
    final fixed=false,
    final max=2,
    final min=0,
    start=1,
    final unit="1")
    "Primary pump speed providing design heat pump flow in cooling mode"
  // Heat pumps, dedicated primary pumps and isolation valves
  // The handling of HP pressure drop is accounted for within the isolation valve component.
  Buildings.Templates.Plants.HeatPumps.Components.HeatPumpGroups.AirToWater hp(
    redeclare final package MediumHeaWat=MediumHeaWat,
    redeclare final package MediumAir=MediumAir,
    final nHp=nHp,
    final is_rev=is_rev,
    final energyDynamics=energyDynamics,
    final have_dpChiHeaWatHp=false,
    final have_dpSou=false,
    final dat=dat.hp,
    final allowFlowReversal=allowFlowReversal,
    final allowFlowReversalSou=false)
    "Heat pump group"
  Components.PumpsPrimaryDedicated pumPri(
    redeclare final package Medium=MediumHeaWat,
    final nHp=nHp,
    final typArrPumPri=typArrPumPri,
    final have_pumChiWatPriDed=have_pumChiWatPriDed,
    final have_pumHeaWatPriVar=have_pumHeaWatPriVar,
    final have_pumChiWatPriVar=have_pumChiWatPriVar,
    final datPumHeaWat=dat.pumHeaWatPri,
    final datPumChiWat=dat.pumChiWatPri,
    final dpValCheHeaWat_nominal=fill(dat.dpValCheHeaWat_nominal,
      pumPri.nPum),
    final dpValCheChiWat_nominal=fill(dat.dpValCheChiWat_nominal,
      if have_pumChiWatPriDed then pumPri.nPum else 0),
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal)
    "Dedicated primary pumps"
  Components.ValvesIsolation valIso(
    redeclare final package Medium=MediumHeaWat,
    final nHp=nHp,
    final have_chiWat=have_chiWat,
    final have_valHpInlIso=have_valHpInlIso,
    final have_valHpOutIso=have_valHpOutIso,
    final have_pumChiWatPriDed=have_pumChiWatPriDed,
    final mHeaWatHp_flow_nominal=fill(dat.hp.mHeaWatHp_flow_nominal, nHp),
    final dpHeaWatHp_nominal=fill(dat.hp.dpHeaWatHp_nominal, nHp),
    final dpBalHeaWatHp_nominal=fill(dpBalHeaWatHp_nominal, nHp),
    final mChiWatHp_flow_nominal=fill(dat.hp.mChiWatHp_flow_nominal, nHp),
    final dpBalChiWatHp_nominal=fill(dpBalChiWatHp_nominal, nHp),
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    linearized=linearized)
    "Heat pump isolation valves"
  // Primary CHW loop
  Buildings.Templates.Components.Pumps.Multiple pumChiWatPri(
    final energyDynamics=energyDynamics,
    redeclare final package Medium=MediumChiWat,
    final dat=dat.pumChiWatPri,
    final dpValChe_nominal=fill(dpValCheChiWat_nominal, nPumChiWatPri),
    final nPum=nPumChiWatPri,
    final have_var=have_pumChiWatPriVar,
    final have_varCom=true,
    final allowFlowReversal=allowFlowReversal)
    if have_chiWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered
    "Headered primary CHW pumps"
  Buildings.Templates.Components.Routing.SingleToMultiple inlPumChiWatPri(
    redeclare final package Medium = MediumChiWat,
    final nPorts=nPumChiWatPri,
    final m_flow_nominal=mChiWatPri_flow_nominal,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final icon_dy=300) if have_chiWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered
    "Primary CHW pumps inlet manifold"
  Buildings.Templates.Components.Routing.MultipleToSingle outPumChiWatPri(
    redeclare final package Medium = MediumChiWat,
    final nPorts=nPumChiWatPri,
    final m_flow_nominal=mChiWatPri_flow_nominal,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final icon_dy=300) if have_chiWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered
    "Primary CHW pumps outlet manifold"
  Buildings.Templates.Components.Routing.PassThroughFluid supChiWatPri(
    redeclare final package Medium = MediumChiWat,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final allowFlowReversal=allowFlowReversal) if have_chiWat and typArrPumPri
     == Buildings.Templates.Components.Types.PumpArrangement.Dedicated
    "Primary CHW supply pipe - Plant with dedicated primary CHW pumps"
  Buildings.Templates.Components.Sensors.VolumeFlowRate VChiWatPri_flow(
    redeclare final package Medium = MediumChiWat,
    final m_flow_nominal=mChiWatPri_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    final have_sen=ctl.have_senVChiWatPri,
    final text_flip=false,
    final typ=Buildings.Templates.Components.Types.SensorVolumeFlowRate.FlowMeter,
    icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply)
    if have_chiWat "Primary CHW volume flow rate"
  Buildings.Templates.Components.Routing.Junction junChiWatBypSup(
    redeclare final package Medium=MediumChiWat,
    final m_flow_nominal=mChiWatPri_flow_nominal * {1, - 1, - 1},
    final energyDynamics=energyDynamics,
    dp_nominal=fill(0, 3),
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Leaving) if have_chiWat
    "Fluid junction"
  Buildings.Templates.Components.Sensors.Temperature TChiWatPriSup(
    redeclare final package Medium = MediumChiWat,
    final have_sen=true,
    final m_flow_nominal=mChiWatPri_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final allowFlowReversal=allowFlowReversal) if have_chiWat
    "Primary CHW supply temperature"
  Buildings.Templates.Components.Routing.Junction junChiWatBypRet(
    redeclare final package Medium = MediumChiWat,
    final m_flow_nominal=mChiWatPri_flow_nominal*{1,-1,1},
    final energyDynamics=energyDynamics,
    dp_nominal=fill(0, 3),
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    icon_pipe1=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    icon_pipe3=Buildings.Templates.Components.Types.IntegrationPoint.Supply)
    if have_chiWat "Fluid junction"
  Buildings.Templates.Components.Sensors.Temperature TChiWatPriRet(
    redeclare final package Medium = MediumChiWat,
    final have_sen=ctl.have_senTChiWatPriRet,
    final m_flow_nominal=mChiWatPri_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    final allowFlowReversal=allowFlowReversal) if have_chiWat
    "Primary CHW return temperature"
  Buildings.Templates.Components.Actuators.Valve valChiWatMinByp(
    redeclare final package Medium=MediumChiWat,
    final dat=dat.valChiWatMinByp,
    final typ=if have_valChiWatMinByp then Buildings.Templates.Components.Types.Valve.TwoWayModulating
      else Buildings.Templates.Components.Types.Valve.None,
    final chaTwo=Buildings.Templates.Components.Types.ValveCharacteristicTwoWay.Linear,
    final allowFlowReversal=allowFlowReversal,
    final energyDynamics=energyDynamics,
    linearized=linearized,
    from_dp=true)
    if have_valChiWatMinByp or have_bypChiWatFix
    "CHW minimum flow bypass valve or fixed bypass depending on type of distribution"
  Buildings.Templates.Components.Tanks.Buffer tanChiWatSup(
    redeclare final package Medium = MediumChiWat,
    final have_tan=typTanChiWat == Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final V=dat.VTanChiWat,
    final m_flow_nominal=mChiWatPri_flow_nominal,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal) if have_chiWat
                                               "CHW buffer tank"
  Buildings.Templates.Components.Tanks.Buffer tanChiWatRet(
    redeclare final package Medium = MediumChiWat,
    final have_tan=typTanChiWat == Buildings.Templates.Components.Types.IntegrationPoint.Return,
    final V=dat.VTanChiWat,
    final m_flow_nominal=mChiWatPri_flow_nominal,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal) if have_chiWat
                                               "CHW buffer tank"
  // Secondary CHW loop
  Buildings.Templates.Components.Pumps.Multiple pumChiWatSec(
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    redeclare final package Medium=MediumChiWat,
    final nPum=nPumChiWatSec,
    final have_var=true,
    final have_varCom=true,
    final dat=dat.pumChiWatSec) if have_chiWat and typPumChiWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized
    "Secondary CHW pumps"
  Buildings.Templates.Components.Routing.SingleToMultiple inlPumChiWatSec(
    redeclare final package Medium = MediumChiWat,
    final nPorts=nPumChiWatSec,
    final m_flow_nominal=mChiWat_flow_nominal,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final icon_dy=300) if have_chiWat and typPumChiWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized
    "Secondary CHW pumps inlet manifold"
  Buildings.Templates.Components.Routing.MultipleToSingle outPumChiWatSec(
    redeclare final package Medium = MediumChiWat,
    final nPorts=nPumChiWatSec,
    final m_flow_nominal=mChiWat_flow_nominal,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final icon_dy=300) if have_chiWat and typPumChiWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized
    "Secondary CHW pumps outlet manifold"
  Buildings.Templates.Components.Routing.PassThroughFluid supChiWatSec(
    redeclare final package Medium = MediumChiWat,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final allowFlowReversal=allowFlowReversal) if have_chiWat and
    typPumChiWatSec <> Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized
    "Secondary CHW supply pipe - Plant without secondary CHW pumps"
  Buildings.Templates.Components.Sensors.VolumeFlowRate VChiWatSec_flow(
    redeclare final package Medium = MediumChiWat,
    final m_flow_nominal=mChiWat_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    final have_sen=ctl.have_senVChiWatSec,
    final text_flip=false,
    final typ=Buildings.Templates.Components.Types.SensorVolumeFlowRate.FlowMeter,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply)
    if have_chiWat "Secondary CHW volume flow rate"
  Buildings.Templates.Components.Sensors.Temperature TChiWatSecSup(
    redeclare final package Medium = MediumChiWat,
    final have_sen=ctl.have_senTChiWatSecSup,
    final m_flow_nominal=mChiWat_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final allowFlowReversal=allowFlowReversal) if have_chiWat
    "Secondary CHW supply temperature"
  Buildings.Templates.Components.Sensors.Temperature TChiWatSecRet(
    redeclare final package Medium = MediumChiWat,
    final have_sen=ctl.have_senTChiWatSecRet,
    final m_flow_nominal=mChiWat_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    final allowFlowReversal=allowFlowReversal) if have_chiWat
    "Secondary CHW return temperature"
  Buildings.Templates.Components.Sensors.DifferentialPressure dpChiWatLoc(
    redeclare final package Medium = MediumChiWat,
    text_rotation=90) if have_chiWat and not ctl.have_senDpChiWatRemWir
    "Local CHW ∆p sensor"
  // Primary HW loop
  Buildings.Templates.Components.Routing.SingleToMultiple inlPumHeaWatPri(
    redeclare final package Medium = MediumHeaWat,
    final nPorts=nPumHeaWatPri,
    final m_flow_nominal=mHeaWatPri_flow_nominal,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final icon_dy=300) if have_heaWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered
    "Primary HW pumps inlet manifold"
  Buildings.Templates.Components.Pumps.Multiple pumHeaWatPri(
    final energyDynamics=energyDynamics,
    redeclare final package Medium=MediumHeaWat,
    final dat=dat.pumHeaWatPri,
    final dpValChe_nominal=fill(dpValCheHeaWat_nominal, nPumHeaWatPri),
    final nPum=nPumHeaWatPri,
    final have_var=have_pumHeaWatPriVar,
    final have_varCom=true,
    final allowFlowReversal=allowFlowReversal)
    if have_heaWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered
    "Headered primary HW pumps"
  Buildings.Templates.Components.Routing.MultipleToSingle outPumHeaWatPri(
    redeclare final package Medium = MediumHeaWat,
    final nPorts=nPumHeaWatPri,
    final m_flow_nominal=mHeaWatPri_flow_nominal,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final icon_dy=300) if have_heaWat and typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered
    "Primary HW pumps outlet manifold"
  Buildings.Templates.Components.Routing.PassThroughFluid supHeaWatPri(
    redeclare final package Medium = MediumHeaWat,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final allowFlowReversal=allowFlowReversal) if have_heaWat and typArrPumPri
     == Buildings.Templates.Components.Types.PumpArrangement.Dedicated
    "Primary HW supply pipe - Plant with dedicated primary HW pumps"
  Buildings.Templates.Components.Sensors.VolumeFlowRate VHeaWatPri_flow(
    redeclare final package Medium = MediumHeaWat,
    final m_flow_nominal=mHeaWatPri_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    final have_sen=ctl.have_senVHeaWatPri,
    final text_flip=false,
    final typ=Buildings.Templates.Components.Types.SensorVolumeFlowRate.FlowMeter,
    icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply)
    "Primary HW volume flow rate"
  Buildings.Templates.Components.Routing.Junction junHeaWatBypSup(
    redeclare final package Medium=MediumHeaWat,
    final m_flow_nominal=mHeaWatPri_flow_nominal * {1, - 1, - 1},
    final energyDynamics=energyDynamics,
    dp_nominal=fill(0, 3),
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Leaving) if have_heaWat
    "Fluid junction"
  Buildings.Templates.Components.Sensors.Temperature THeaWatPriSup(
    redeclare final package Medium = MediumHeaWat,
    final have_sen=true,
    final m_flow_nominal=mHeaWatPri_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final allowFlowReversal=allowFlowReversal) "Primary HW supply temperature"
  Buildings.Templates.Components.Sensors.Temperature THeaWatPriRet(
    redeclare final package Medium = MediumHeaWat,
    final have_sen=ctl.have_senTHeaWatPriRet,
    final m_flow_nominal=mHeaWatPri_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    final allowFlowReversal=allowFlowReversal) "Primary HW return temperature"
  Buildings.Templates.Components.Routing.Junction junHeaWatBypRet(
    redeclare final package Medium = MediumHeaWat,
    final m_flow_nominal=mHeaWatPri_flow_nominal*{1,-1,1},
    final energyDynamics=energyDynamics,
    dp_nominal=fill(0, 3),
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    icon_pipe1=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    icon_pipe3=Buildings.Templates.Components.Types.IntegrationPoint.Supply)
    if have_heaWat "Fluid junction"
  Buildings.Templates.Components.Actuators.Valve valHeaWatMinByp(
    redeclare final package Medium = MediumHeaWat,
    final dat=dat.valHeaWatMinByp,
    final typ=if have_valHeaWatMinByp then Buildings.Templates.Components.Types.Valve.TwoWayModulating
         else Buildings.Templates.Components.Types.Valve.None,
    final chaTwo=Buildings.Templates.Components.Types.ValveCharacteristicTwoWay.Linear,
    final allowFlowReversal=allowFlowReversal,
    final energyDynamics=energyDynamics,
    linearized=linearized,
    from_dp=true)
    if have_valHeaWatMinByp or have_bypHeaWatFix
    "HW minimum flow bypass valve or fixed bypass depending on type of distribution"
  Buildings.Templates.Components.Tanks.Buffer tanHeaWatSup(
    redeclare final package Medium = MediumHeaWat,
    final have_tan=typTanHeaWat == Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final V=dat.VTanHeaWat,
    final m_flow_nominal=mHeaWatPri_flow_nominal,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal) if have_heaWat
                                               "HW buffer tank"
  Buildings.Templates.Components.Tanks.Buffer tanHeaWatRet(
    redeclare final package Medium = MediumHeaWat,
    final have_tan=typTanHeaWat == Buildings.Templates.Components.Types.IntegrationPoint.Return,
    final V=dat.VTanHeaWat,
    final m_flow_nominal=mHeaWatPri_flow_nominal,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal) if have_heaWat
                                               "HW buffer tank"
  // Secondary HW loop
  Buildings.Templates.Components.Pumps.Multiple pumHeaWatSec(
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    redeclare final package Medium=MediumHeaWat,
    final nPum=nPumHeaWatSec,
    final have_var=true,
    final have_varCom=true,
    final dat=dat.pumHeaWatSec)
    if typPumHeaWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized
    "Secondary HW pumps"
  Buildings.Templates.Components.Routing.SingleToMultiple inlPumHeaWatSec(
    redeclare final package Medium = MediumHeaWat,
    final nPorts=nPumHeaWatSec,
    final m_flow_nominal=mHeaWat_flow_nominal,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final icon_dy=300) if typPumHeaWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized
    "Secondary HW pumps inlet manifold"
  Buildings.Templates.Components.Routing.MultipleToSingle outPumHeaWatSec(
    redeclare final package Medium = MediumHeaWat,
    final nPorts=nPumHeaWatSec,
    final m_flow_nominal=mHeaWat_flow_nominal,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final icon_dy=300) if typPumHeaWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized
    "Secondary HW pumps outlet manifold"
  Buildings.Templates.Components.Routing.PassThroughFluid supHeaWatSec(
    redeclare final package Medium = MediumHeaWat,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final allowFlowReversal=allowFlowReversal) if have_heaWat and
    typPumHeaWatSec <> Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized
    "Secondary HW supply pipe - Plant without secondary HW pumps"
  Buildings.Templates.Components.Sensors.VolumeFlowRate VHeaWatSec_flow(
    redeclare final package Medium = MediumHeaWat,
    final m_flow_nominal=mHeaWat_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    final have_sen=ctl.have_senVHeaWatSec,
    final text_flip=false,
    final typ=Buildings.Templates.Components.Types.SensorVolumeFlowRate.FlowMeter,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply)
    "Secondary HW volume flow rate"
  Buildings.Templates.Components.Sensors.Temperature THeaWatSecSup(
    redeclare final package Medium = MediumHeaWat,
    final have_sen=ctl.have_senTHeaWatSecSup,
    final m_flow_nominal=mHeaWat_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Supply,
    final allowFlowReversal=allowFlowReversal)
    "Secondary HW supply temperature"
  Buildings.Templates.Components.Sensors.Temperature THeaWatSecRet(
    redeclare final package Medium = MediumHeaWat,
    final have_sen=ctl.have_senTHeaWatSecRet,
    final m_flow_nominal=mHeaWat_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    final allowFlowReversal=allowFlowReversal)
    "Secondary HW return temperature"
  Buildings.Templates.Components.Sensors.DifferentialPressure dpHeaWatLoc(
    redeclare final package Medium = MediumHeaWat,
    text_rotation=90) if have_heaWat and not ctl.have_senDpHeaWatRemWir
    "Local HW ∆p sensor"
  Components.HeatRecoveryChiller hrc(
    redeclare final package MediumChiWat=MediumChiWat,
    redeclare final package MediumHeaWat=MediumHeaWat,
    final allowFlowReversal1=allowFlowReversal,
    final allowFlowReversal2=allowFlowReversal,
    final show_T=show_T,
    final datPumChiWat=dat.pumChiWatHrc,
    final datPumHeaWat=dat.pumHeaWatHrc,
    final datHrc=dat.hrc,
    final energyDynamics=energyDynamics) if have_hrc
    "Sidestream heat recovery chiller"
  Buildings.Templates.Components.Routing.Junction junHeaWatHrcEnt(
    redeclare final package Medium = MediumHeaWat,
    final m_flow_nominal=mHeaWat_flow_nominal*{1,-1,-1},
    final energyDynamics=energyDynamics,
    dp_nominal=fill(0, 3),
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    icon_pipe1=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    icon_pipe3=if have_hrc then Buildings.Templates.Components.Types.IntegrationPoint.Return
    else Buildings.Templates.Components.Types.IntegrationPoint.None)
    if have_heaWat "Fluid junction"
  Buildings.Templates.Components.Routing.Junction junHeaWatHrcLvg(
    redeclare final package Medium = MediumHeaWat,
    final m_flow_nominal=mHeaWat_flow_nominal*{1,-1,1},
    final energyDynamics=energyDynamics,
    dp_nominal=fill(0, 3),
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    icon_pipe1=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    icon_pipe3=if have_hrc then Buildings.Templates.Components.Types.IntegrationPoint.Supply
    else Buildings.Templates.Components.Types.IntegrationPoint.None)
    if have_heaWat "Fluid junction"
  Buildings.Templates.Components.Routing.Junction junChiWatHrcEnt(
    redeclare final package Medium = MediumChiWat,
    final m_flow_nominal=mChiWat_flow_nominal*{1,-1,-1},
    final energyDynamics=energyDynamics,
    dp_nominal=fill(0, 3),
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    icon_pipe1=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    icon_pipe3=if have_hrc then Buildings.Templates.Components.Types.IntegrationPoint.Return
    else Buildings.Templates.Components.Types.IntegrationPoint.None)
    if have_chiWat "Fluid junction"
  Buildings.Templates.Components.Routing.Junction junChiWatHrcLvg(
    redeclare final package Medium = MediumChiWat,
    final m_flow_nominal=mChiWat_flow_nominal*{1,-1,1},
    final energyDynamics=energyDynamics,
    dp_nominal=fill(0, 3),
    final portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    icon_pipe1=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    icon_pipe3=if have_hrc then Buildings.Templates.Components.Types.IntegrationPoint.Supply
    else Buildings.Templates.Components.Types.IntegrationPoint.None)
    if have_chiWat "Fluid junction"
  Buildings.Templates.Components.Sensors.Temperature TChiWatRetUpsHrc(
    redeclare final package Medium = MediumChiWat,
    final have_sen=have_hrc,
    final m_flow_nominal=mChiWat_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    final allowFlowReversal=allowFlowReversal) if have_chiWat
    "CHW return temperature upstream of HRC"
  Buildings.Templates.Components.Sensors.Temperature THeaWatRetUpsHrc(
    redeclare final package Medium = MediumHeaWat,
    final have_sen=have_hrc,
    final m_flow_nominal=mHeaWat_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.InWell,
    final icon_pipe=Buildings.Templates.Components.Types.IntegrationPoint.Return,
    final allowFlowReversal=allowFlowReversal)
    "HW return temperature upstream of HRC"
  Fluid.Sources.Boundary_pT bouHeaWat(
    redeclare final package Medium = MediumHeaWat,
    p=Buildings.Templates.Data.Defaults.pHeaWat_rel_nominal + 101325,
    nPorts=1) if have_heaWat
    "Pressure boundary condition mimicking expansion tank"
initial equation
  // Calculation of pump speed providing design flow.
  if is_dpBalYPumSetCal
    and have_heaWat
    and typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2
    and typPumHeaWatPri==Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable then
    0=Buildings.Templates.Utilities.computeBalancingPressureDrop(
      m_flow_nominal=hp.mHeaWatHp_flow_nominal,
      dp_nominal=max(valIso.dpHeaWat_nominal) + dpValCheHeaWat_nominal,
      datPum=dat.pumHeaWatPriSin[1],
      r_N=yPumHeaWatPriSet);
  else
    yPumHeaWatPriSet=dat.ctl.yPumHeaWatPriSet;
  end if;
  if is_dpBalYPumSetCal
    and have_chiWat
    and typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2
    and (typPumChiWatPri==Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable
      or typPumChiWatPri==Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.None
      and typPumHeaWatPri==Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable) then
    0=Buildings.Templates.Utilities.computeBalancingPressureDrop(
      m_flow_nominal=hp.mChiWatHp_flow_nominal,
      dp_nominal=max(valIso.dpChiWat_nominal) + dpValCheChiWat_nominal,
      datPum=if typPumChiWatPri==Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable
        then dat.pumChiWatPriSin[1] else dat.pumHeaWatPriSin[1],
      r_N=yPumChiWatPriSet);
  else
    yPumChiWatPriSet=dat.ctl.yPumChiWatPriSet;
  end if;
  if is_dpBalYPumSetCal then
    if have_heaWat then
      assert(dpBalHeaWatHp_nominal>=0,
        "In "+ getInstanceName() + ": "+
        "The calculated pressure drop for the HW balancing valve is negative, "+
        "indicating that the primary pump curve needs to be revised.");
      assert(yPumHeaWatPriSet >= 0.1 and yPumHeaWatPriSet <= 2,
        "In "+ getInstanceName() + ": "+
        "The calculated primary pump speed to provide the design HW flow is out of bounds, "+
        "indicating that the primary pump curve needs to be revised.");
    end if;
    if have_chiWat then
      assert(dpBalChiWatHp_nominal>=0,
        "In "+ getInstanceName() + ": "+
        "The calculated pressure drop for the CHW balancing valve is negative, "+
        "indicating that the primary pump curve needs to be revised.");
      assert(yPumChiWatPriSet >= 0.1 and yPumChiWatPriSet <= 2,
        "In "+ getInstanceName() + ": "+
        "The calculated primary pump speed to provide the design CHW flow is out of bounds, "+
        "indicating that the primary pump curve needs to be revised.");
    end if;
  end if;
equation
  /* Control point connection - start */
  connect(busWea, hp.busWea);
  connect(bus, hp.bus);
  connect(bus, hrc.bus);
  connect(bus, pumPri.bus);
  connect(bus, valIso.bus);
  connect(bus.pumChiWatPri, pumChiWatPri.bus);
  connect(bus.pumHeaWatPri, pumHeaWatPri.bus);
  connect(bus.pumChiWatSec, pumChiWatSec.bus);
  connect(bus.pumHeaWatSec, pumHeaWatSec.bus);
  connect(bus.valChiWatMinByp, valChiWatMinByp.bus);
  connect(bus.valHeaWatMinByp, valHeaWatMinByp.bus);
  connect(VChiWatPri_flow.y, bus.VChiWatPri_flow);
  connect(VHeaWatPri_flow.y, bus.VHeaWatPri_flow);
  connect(VChiWatSec_flow.y, bus.VChiWatSec_flow);
  connect(VHeaWatSec_flow.y, bus.VHeaWatSec_flow);
  connect(TChiWatPriSup.y, bus.TChiWatPriSup);
  connect(THeaWatPriSup.y, bus.THeaWatPriSup);
  connect(TChiWatPriRet.y, bus.TChiWatPriRet);
  connect(THeaWatPriRet.y, bus.THeaWatPriRet);
  connect(TChiWatSecSup.y, bus.TChiWatSecSup);
  connect(THeaWatSecSup.y, bus.THeaWatSecSup);
  connect(TChiWatSecRet.y, bus.TChiWatSecRet);
  connect(THeaWatSecRet.y, bus.THeaWatSecRet);
  connect(THeaWatRetUpsHrc.y, bus.THeaWatRetUpsHrc);
  connect(TChiWatRetUpsHrc.y, bus.TChiWatRetUpsHrc);
  connect(dpHeaWatLoc.y, bus.dpHeaWatLoc);
  connect(dpChiWatLoc.y, bus.dpChiWatLoc);
  /* Control point connection - stop */
  connect(pumChiWatPri.ports_b, outPumChiWatPri.ports_a)
  connect(inlPumChiWatPri.ports_b, pumChiWatPri.ports_a)
  connect(valIso.port_bChiWat, inlPumChiWatPri.port_a)
  connect(hp.ports_bChiHeaWat, pumPri.ports_aChiHeaWatHp)
  connect(pumPri.ports_bChiHeaWat, valIso.ports_aChiHeaWatHp)
  connect(pumPri.ports_bHeaWat, valIso.ports_aHeaWatHp)
  connect(pumPri.ports_bChiWat, valIso.ports_aChiWatHp)
  connect(outPumChiWatPri.port_b, VChiWatPri_flow.port_a)
  connect(VChiWatPri_flow.port_b, TChiWatPriSup.port_a)
  connect(pumChiWatSec.ports_b, outPumChiWatSec.ports_a)
  connect(inlPumChiWatSec.ports_b, pumChiWatSec.ports_a)
  connect(valIso.port_bChiWat, supChiWatPri.port_a)
  connect(supChiWatPri.port_b, VChiWatPri_flow.port_a)
  connect(valIso.ports_bChiHeaWatHp, pumPri.ports_aChiHeaWat)
  connect(pumPri.ports_bChiHeaWatHp, hp.ports_aChiHeaWat)
  connect(supChiWatSec.port_b, VChiWatSec_flow.port_a)

  connect(port_bChiWat, dpChiWatLoc.port_a)
  connect(dpChiWatLoc.port_b, port_aChiWat)
  connect(port_bHeaWat, dpHeaWatLoc.port_a)
  connect(dpHeaWatLoc.port_b, port_aHeaWat)
  connect(pumHeaWatPri.ports_b, outPumHeaWatPri.ports_a)
  connect(inlPumHeaWatPri.ports_b, pumHeaWatPri.ports_a)
  connect(outPumHeaWatPri.port_b, VHeaWatPri_flow.port_a)
  connect(VHeaWatPri_flow.port_b, THeaWatPriSup.port_a)
  connect(pumHeaWatSec.ports_b, outPumHeaWatSec.ports_a)
  connect(inlPumHeaWatSec.ports_b, pumHeaWatSec.ports_a)
  connect(supHeaWatPri.port_b, VHeaWatPri_flow.port_a)
  connect(supHeaWatSec.port_b, VHeaWatSec_flow.port_a)
  connect(outPumHeaWatSec.port_b, VHeaWatSec_flow.port_a)
  connect(valIso.port_bHeaWat, inlPumHeaWatPri.port_a)
  connect(VHeaWatSec_flow.port_b, port_bHeaWat)
  connect(valIso.port_bHeaWat, supHeaWatPri.port_a)
  connect(junChiWatBypSup.port_2, TChiWatSecSup.port_a)
  connect(TChiWatSecSup.port_b, inlPumChiWatSec.port_a)
  connect(junChiWatBypRet.port_1, TChiWatSecRet.port_b)
  connect(junHeaWatBypSup.port_2, THeaWatSecSup.port_a)
  connect(THeaWatSecSup.port_b, inlPumHeaWatSec.port_a)
  connect(THeaWatSecSup.port_b, supHeaWatSec.port_a)
  connect(TChiWatSecSup.port_b, supChiWatSec.port_a)
  connect(junHeaWatBypRet.port_1, THeaWatSecRet.port_b)
  connect(outPumChiWatSec.port_b, VChiWatSec_flow.port_a)
  connect(TChiWatPriRet.port_b, valIso.port_aChiWat)
  connect(junHeaWatHrcEnt.port_2, junHeaWatHrcLvg.port_1)
  connect(junHeaWatHrcLvg.port_2, THeaWatSecRet.port_a)
  connect(junHeaWatHrcEnt.port_3, hrc.port_a1)
  connect(hrc.port_b1, junHeaWatHrcLvg.port_3)
  connect(junChiWatHrcEnt.port_3, hrc.port_a2)
  connect(junChiWatHrcEnt.port_2, junChiWatHrcLvg.port_1)
  connect(junChiWatHrcLvg.port_2, TChiWatSecRet.port_a)
  connect(hrc.port_b2, junChiWatHrcLvg.port_3)
  connect(port_aChiWat, TChiWatRetUpsHrc.port_a)
  connect(TChiWatRetUpsHrc.port_b, junChiWatHrcEnt.port_1)
  connect(port_aHeaWat, THeaWatRetUpsHrc.port_a)
  connect(THeaWatRetUpsHrc.port_b, junHeaWatHrcEnt.port_1)
  connect(junChiWatBypSup.port_3, valChiWatMinByp.port_a)
  connect(valChiWatMinByp.port_b, junChiWatBypRet.port_3)
  connect(junHeaWatBypSup.port_3, valHeaWatMinByp.port_a)
  connect(valHeaWatMinByp.port_b, junHeaWatBypRet.port_3)
  connect(VChiWatSec_flow.port_b, port_bChiWat)
  connect(TChiWatPriSup.port_b, tanChiWatSup.port_a)
  connect(tanChiWatSup.port_b, junChiWatBypSup.port_1)
  connect(junChiWatBypRet.port_2, tanChiWatRet.port_a)
  connect(tanChiWatRet.port_b, TChiWatPriRet.port_a)
  connect(THeaWatPriSup.port_b, tanHeaWatSup.port_a)
  connect(tanHeaWatSup.port_b, junHeaWatBypSup.port_1)
  connect(junHeaWatBypRet.port_2, tanHeaWatRet.port_a)
  connect(tanHeaWatRet.port_b, THeaWatPriRet.port_a)
  connect(bouHeaWat.ports[1], THeaWatPriRet.port_b)
  connect(THeaWatPriRet.port_b, valIso.port_aHeaWat)
end AirToWater;


Heat pump plant

within Buildings.Templates.Plants;
package HeatPumps "Heat pump plant"
  extends Modelica.Icons.Package;
end HeatPumps;


Package with type definitions

within Buildings.Templates.Plants.HeatPumps;
package Types
  "Package with type definitions"
  extends Modelica.Icons.TypesPackage;
  type Controller = enumeration(
    AirToWater
      "Controller for AWHP plant",
    OpenLoop
      "Open loop controller")
    "Enumeration to specify the plant controller";
  type Distribution = enumeration(
    Constant1Only
      "Constant primary-only",
    Variable1Only
      "Variable primary-only",
    Constant1Variable2
      "Constant primary - Variable secondary centralized",
    Variable1And2
      "Variable primary - Variable secondary centralized")
    "Enumeration to specify the type of CHW/HW distribution system";
  type PumpsPrimary = enumeration(
    Constant
      "Constant speed pump specified separately",
    Variable
      "Variable speed pump specified separately",
    None
      "No pump")
    "Enumeration to specify the type of primary pumps";
  type PumpsSecondary = enumeration(
    None
      "No secondary pumps (primary-only)",
    Centralized
      "Variable secondary centralized")
    "Enumeration to specify the type of secondary HW pumps";
end Types;


within Buildings.Templates.Plants.HeatPumps.Components;
model HeatRecoveryChiller
  "Heat recovery chiller for sidestream integration"
  extends Buildings.Fluid.Interfaces.PartialFourPortInterface(
    redeclare final package Medium1=MediumHeaWat,
    redeclare final package Medium2=MediumChiWat,
    final m1_flow_nominal=datHrc.mCon_flow_nominal,
    final m2_flow_nominal=datHrc.mChiWat_flow_nominal)
  /* RFE(AntoineGautier): IconMap is used above until the following PR is completed:
  https://github.com/ibpsa/modelica-ibpsa/issues/1781
  Note that the extent annotation results in flipping the icon vertically (port_*2 at the top),
  which allows better integration into the HP plant diagram.
  Ideally, with PR#1781, port_a1 and port_b1 should be moved to be vertically
  aligned with port_a2 and port_b2, respectively.
  */replaceable package MediumChiWat=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "CHW medium"
  replaceable package MediumHeaWat=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "HW medium"
  parameter Buildings.Templates.Components.Data.PumpSingle datPumChiWat
    "HRC CHW pump parameters"
  parameter Buildings.Templates.Components.Data.PumpSingle datPumHeaWat
    "HRC HW pump parameters"
  parameter Buildings.Templates.Components.Data.Chiller datHrc
    "HRC parameters"
  parameter Modelica.Units.SI.Time tauHrc=30
    "HRC – Time constant at nominal flow, used if energy or mass balance is dynamic"
  parameter Modelica.Units.SI.Time tauPum=1
    "Pump – Time constant of fluid volume for nominal flow, used if energy or mass balance is dynamic"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  Buildings.Templates.Plants.HeatPumps.Interfaces.Bus bus
    "Plant control bus"
  Buildings.Templates.Components.Chillers.Compression hrc(
    redeclare final package MediumChiWat=MediumChiWat,
    redeclare final package MediumCon=MediumHeaWat,
    final dat=datHrc,
    final typ=Buildings.Templates.Components.Types.Chiller.WaterCooled,
    final have_switchover=true,
    final energyDynamics=energyDynamics,
    final tau=tauHrc,
    final allowFlowReversal1=allowFlowReversal1,
    final allowFlowReversal2=allowFlowReversal2,
    final show_T=show_T)
    "Heat recovery chiller"
  Buildings.Templates.Components.Pumps.Single pumChiWat(
    have_var=false,
    have_valChe=false,
    redeclare final package Medium=MediumChiWat,
    final dat=datPumChiWat,
    final energyDynamics=energyDynamics,
    final tau=tauPum,
    final allowFlowReversal=allowFlowReversal2,
    final show_T=show_T)
    "HRC CHW pump"
  Buildings.Templates.Components.Pumps.Single pumHeaWat(
    have_var=false,
    have_valChe=false,
    redeclare final package Medium=MediumHeaWat,
    final dat=datPumHeaWat,
    final energyDynamics=energyDynamics,
    final tau=tauPum,
    final allowFlowReversal=allowFlowReversal1,
    final show_T=show_T)
    "HRC HW pump"
equation
  connect(port_a1, pumHeaWat.port_a)
  connect(port_a2, pumChiWat.port_a)
  connect(pumChiWat.port_b, hrc.port_a2)
  connect(hrc.port_b2, port_b2)
  connect(pumHeaWat.port_b, hrc.port_a1)
  connect(hrc.port_b1, port_b1)
  connect(bus.hrc, hrc.bus)
  connect(bus.pumHeaWatHrc, pumHeaWat.bus)
  connect(bus.pumChiWatHrc, pumChiWat.bus)
end HeatRecoveryChiller;


Package with component models

within Buildings.Templates.Plants.HeatPumps;
package Components "Package with component models"
  extends Modelica.Icons.VariantsPackage;
end Components;


Dedicated primary pumps

within Buildings.Templates.Plants.HeatPumps.Components;
model PumpsPrimaryDedicated
  "Dedicated primary pumps"
  replaceable package Medium=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Medium model"
  parameter Integer nHp(min=1)
    "Number of heat pumps"
  /* RFE(AntoineGautier): Add support for multiple pumps for each heat pump.
  Currently, only one dedicated CHW or HW pump for each HP is supported.
  */
  final parameter Integer nPum=if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated
    then nHp else 0
    "Number of primary pumps"
  parameter Buildings.Templates.Components.Types.PumpArrangement typArrPumPri
    "Type of primary pump arrangement"
  parameter Boolean have_pumChiWatPriDed(start=false)
    "Set to true for plants with separate dedicated primary CHW pumps"
  parameter Boolean have_pumHeaWatPriVar(start=false)
    "Set to true for variable speed primary HW pumps"
  parameter Boolean have_pumChiWatPriVar(start=false)
    "Set to true for variable speed primary CHW pumps"
  parameter Buildings.Templates.Components.Data.PumpMultiple datPumHeaWat(
    typ=if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated
      then Buildings.Templates.Components.Types.Pump.Multiple else Buildings.Templates.Components.Types.Pump.None,
    nPum=nPum)
    "HW pump parameters"
  parameter Buildings.Templates.Components.Data.PumpMultiple datPumChiWat(
    typ=if have_pumChiWatPriDed then Buildings.Templates.Components.Types.Pump.Multiple
      else Buildings.Templates.Components.Types.Pump.None,
    nPum=if have_pumChiWatPriDed then nPum else 0)
    "CHW pump parameters"
  parameter Modelica.Units.SI.PressureDifference dpValCheHeaWat_nominal[nPum](
    each final min=0,
    start=fill(if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated
         then Buildings.Templates.Data.Defaults.dpValChe else 0, nPum))=fill(
    if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated
     then Buildings.Templates.Data.Defaults.dpValChe else 0, nPum)
    "HW pump check valve pressure drop at design pump flow rate (selection conditions)"
  parameter Modelica.Units.SI.PressureDifference dpValCheChiWat_nominal[if have_pumChiWatPriDed then nPum else 0](
    each final min=0,
    start=fill(if have_pumChiWatPriDed then Buildings.Templates.Data.Defaults.dpValChe
         else 0, if have_pumChiWatPriDed then nPum else 0))=fill(if
    have_pumChiWatPriDed then Buildings.Templates.Data.Defaults.dpValChe else 0,
    if have_pumChiWatPriDed then nPum else 0)
    "CHW pump check valve pressure drop at design pump flow rate (selection conditions)"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  parameter Modelica.Units.SI.Time tau=1
    "Time constant at nominal flow"
  parameter Boolean allowFlowReversal=true
    "Set to false to simplify equations, assuming, but not enforcing, no flow reversal"
  Modelica.Fluid.Interfaces.FluidPorts_b ports_bChiHeaWat[nHp](
    redeclare each final package Medium=Medium,
    each m_flow(
      max=if allowFlowReversal then + Modelica.Constants.inf else 0),
    each h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Headered
      or typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated
      and not have_pumChiWatPriDed
    "CHW/HW supply (to primary loop)"
  Modelica.Fluid.Interfaces.FluidPorts_a ports_aChiHeaWat[nHp](
    redeclare each final package Medium=Medium,
    each m_flow(
      min=if allowFlowReversal then - Modelica.Constants.inf else 0),
    each h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    "CHW/HW return (from primary loop)"
  Modelica.Fluid.Interfaces.FluidPorts_b ports_bChiHeaWatHp[nHp](
    redeclare each final package Medium=Medium,
    each m_flow(
      max=if allowFlowReversal then + Modelica.Constants.inf else 0),
    each h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    "CHW/HW return (HP entering)"
  Modelica.Fluid.Interfaces.FluidPorts_b ports_bHeaWat[nHp](
    redeclare each final package Medium=Medium,
    each m_flow(
      min=if allowFlowReversal then - Modelica.Constants.inf else 0),
    each h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated
      and have_pumChiWatPriDed
    "HW supply (to primary loop)"
  Modelica.Fluid.Interfaces.FluidPorts_b ports_bChiWat[nHp](
    redeclare each final package Medium=Medium,
    each m_flow(
      min=if allowFlowReversal then - Modelica.Constants.inf else 0),
    each h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated
      and have_pumChiWatPriDed
    "CHW supply (to primary loop)"
  Modelica.Fluid.Interfaces.FluidPorts_a ports_aChiHeaWatHp[nHp](
    redeclare each final package Medium=Medium,
    each m_flow(
      min=if allowFlowReversal then - Modelica.Constants.inf else 0),
    each h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    "CHW/HW supply (HP leaving)"
  Buildings.Templates.Plants.HeatPumps.Interfaces.Bus bus
    "Plant control bus"
  Buildings.Templates.Components.Pumps.Multiple pumHeaWat(
    redeclare final package Medium=Medium,
    final have_var=have_pumHeaWatPriVar,
    final have_varCom=false,
    final nPum=nPum,
    final dat=datPumHeaWat,
    final dpValChe_nominal=dpValCheHeaWat_nominal,
    final allowFlowReversal=allowFlowReversal,
    final tau=tau,
    final energyDynamics=energyDynamics)
    if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated
    "Dedicated primary (HW) Pumps"
  Buildings.Templates.Components.Pumps.Multiple pumChiWat(
    redeclare final package Medium=Medium,
    final have_var=have_pumChiWatPriVar,
    final have_varCom=false,
    final nPum=if have_pumChiWatPriDed then nPum else 0,
    final dat=datPumChiWat,
    final dpValChe_nominal=dpValCheChiWat_nominal,
    final allowFlowReversal=allowFlowReversal,
    final tau=tau,
    final energyDynamics=energyDynamics)
    if have_pumChiWatPriDed
    "Dedicated primary CHW pumps - Optional"
  Buildings.Templates.Components.Routing.PassThroughFluid pasHdr[nHp](
      redeclare each final package Medium = Medium) if typArrPumPri ==
    Buildings.Templates.Components.Types.PumpArrangement.Headered
    "Direct fluid pass-through for headered primary pumps"
  Fluid.FixedResistances.Junction junDedSep[nPum](
    redeclare each final package Medium =Medium,
    final m_flow_nominal={{
      max(datPumHeaWat.m_flow_nominal[i], datPumChiWat.m_flow_nominal[i]),
      -datPumHeaWat.m_flow_nominal[i],
      -datPumChiWat.m_flow_nominal[i]} for i in 1:nPum},
    dp_nominal=fill(fill(0, 3), nPum),
    each final energyDynamics=energyDynamics,
    each final portFlowDirection_1=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional else
      Modelica.Fluid.Types.PortFlowDirection.Entering,
    each final portFlowDirection_2=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional else
      Modelica.Fluid.Types.PortFlowDirection.Leaving,
   each final portFlowDirection_3=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional else
      Modelica.Fluid.Types.PortFlowDirection.Leaving)
    if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated
     and have_pumChiWatPriDed
    "Fluid junction for separate dedicated primary pumps"
  Buildings.Templates.Components.Routing.PassThroughFluid pasDedCom[nHp](
      redeclare each final package Medium = Medium) if typArrPumPri ==
    Buildings.Templates.Components.Types.PumpArrangement.Dedicated and not
    have_pumChiWatPriDed
    "Direct fluid pass-through for common dedicated primary pumps"
protected
  Buildings.Templates.Components.Interfaces.Bus busPumHeaWatPri
    "Primary HW pump control bus"
  Buildings.Templates.Components.Interfaces.Bus busPumChiWatPri
    if have_pumChiWatPriDed
    "Primary CHW pump control bus"
equation
  connect(bus.pumHeaWatPri, busPumHeaWatPri)
  connect(bus.pumChiWatPri, busPumChiWatPri)
  connect(pumHeaWat.ports_b, ports_bHeaWat)
  connect(pumHeaWat.ports_b, ports_bChiHeaWat)
  connect(pumChiWat.ports_b, ports_bChiWat)
  connect(busPumHeaWatPri, pumHeaWat.bus)
  connect(busPumChiWatPri, pumChiWat.bus)
  connect(ports_aChiHeaWat, ports_bChiHeaWatHp)
  connect(ports_aChiHeaWatHp, pasHdr.port_a)
  connect(pasHdr.port_b, ports_bChiHeaWat)
  connect(junDedSep.port_3, pumChiWat.ports_a)
  connect(ports_aChiHeaWatHp, pasDedCom.port_a)
  connect(pasDedCom.port_b, pumHeaWat.ports_a)
  connect(ports_aChiHeaWatHp, junDedSep.port_1)
  connect(junDedSep.port_2, pumHeaWat.ports_a)
end PumpsPrimaryDedicated;


Heat pump isolation valves

within Buildings.Templates.Plants.HeatPumps.Components;
model ValvesIsolation
  "Heat pump isolation valves"
  replaceable package Medium=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Medium model"
  final parameter Buildings.Templates.Components.Types.Valve typ=
    Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition
    "Valve type"
  parameter Integer nHp(
    final min=1)
    "Number of heat pumps"
  parameter Boolean have_chiWat
    "Set to true if the plant provides CHW"
  parameter Boolean have_valHpInlIso
    "Set to true for isolation valves at HP inlet"
  parameter Boolean have_valHpOutIso
    "Set to true for isolation valves at HP outlet"
  parameter Boolean have_pumChiWatPriDed(
    start=false)
    "Set to true for plants with separate dedicated primary CHW pumps"
  parameter Modelica.Units.SI.MassFlowRate mHeaWatHp_flow_nominal[nHp](
    each final min=0,
    each start=0)
    "HW mass flow rate - Each heat pump"
  parameter Modelica.Units.SI.PressureDifference dpHeaWatHp_nominal[nHp](
    each final min=0,
    each start=Buildings.Templates.Data.Defaults.dpChiWatChi)
    "Pressure drop at design HW mass flow rate - Each heat pump"
  parameter Modelica.Units.SI.PressureDifference dpBalHeaWatHp_nominal[nHp](
    each final min=0)=fill(0, nHp)
    "Balancing valve pressure drop at design HW mass flow rate - Each heat pump"
  parameter Modelica.Units.SI.MassFlowRate mChiWatHp_flow_nominal[nHp](
    each start=0,
    each final min=0)
    "CHW mass flow rate - Each heat pump"
  final parameter Modelica.Units.SI.PressureDifference dpChiWatHp_nominal[nHp]=
    dpHeaWatHp_nominal .*(mChiWatHp_flow_nominal ./ mHeaWatHp_flow_nominal) .^ 2
    "Pressure drop at design CHW mass flow rate - Each heat pump"
  parameter Modelica.Units.SI.PressureDifference dpBalChiWatHp_nominal[nHp](
    each final min=0,
    each start=0)=fill(0, nHp)
    "Balancing valve pressure drop at design CHW mass flow rate - Each heat pump"
  parameter Modelica.Units.SI.PressureDifference dpValveHeaWat_nominal[nHp]=
    fill(Buildings.Templates.Data.Defaults.dpValIso, nHp)
    "HW isolation valve pressure drop (identical for inlet and outlet valves)"
  final parameter Modelica.Units.SI.PressureDifference dpFixedHeaWat_nominal[nHp]=
    dpHeaWatHp_nominal + dpBalHeaWatHp_nominal
    "Fixed HW pressure drop: HP + balancing valve"
  // The following parameter is intended for external use.
  final parameter Modelica.Units.SI.PressureDifference dpHeaWat_nominal[nHp]=
    dpFixedHeaWat_nominal +
    (if have_valHpOutIso then dpValveHeaWat_nominal else fill(0, nHp)) +
    (if have_valHpInlIso then dpValveHeaWat_nominal else fill(0, nHp))
    "Total HW pressure drop: fixed + valves"
  parameter Modelica.Units.SI.PressureDifference dpValveChiWat_nominal[nHp](
    each start=0)=fill(Buildings.Templates.Data.Defaults.dpValIso, nHp)
    "Isolation valve CHW pressure drop (identical for inlet and outlet valves)"
  final parameter Modelica.Units.SI.PressureDifference dpFixedChiWat_nominal[nHp]=
    if have_chiWat then dpBalChiWatHp_nominal + dpChiWatHp_nominal else fill(0, nHp)
    "Total fixed CHW pressure drop"
  // The following parameter is intended for external use.
  final parameter Modelica.Units.SI.PressureDifference dpChiWat_nominal[nHp]=
    if have_chiWat then dpFixedChiWat_nominal +
      (if have_valHpOutIso then dpValveChiWat_nominal else fill(0, nHp)) +
      (if have_valHpInlIso then dpValveChiWat_nominal else fill(0, nHp))
    else fill(0, nHp)
    "Total CHW pressure drop: fixed + valves"
  final parameter Buildings.Templates.Components.Data.Valve datValHeaWatHpOutIso[nHp](
    each typ=typ,
    m_flow_nominal=mHeaWatHp_flow_nominal,
    dpValve_nominal=dpValveHeaWat_nominal,
    dpFixed_nominal=dpFixedHeaWat_nominal)
    "Heat pump outlet HW isolation valve parameters"
  // dpFixed_nominal only applied to inlet valves if there is no outlet valve.
  final parameter Buildings.Templates.Components.Data.Valve datValHeaWatHpInlIso[nHp](
    each typ=typ,
    m_flow_nominal=mHeaWatHp_flow_nominal,
    dpValve_nominal=dpValveHeaWat_nominal,
    dpFixed_nominal=if not have_valHpOutIso then dpFixedHeaWat_nominal else fill(0, nHp))
    "Heat pump inlet HW isolation valve parameters"
  final parameter Buildings.Templates.Components.Data.Valve datValChiWatHpOutIso[nHp](
    each typ=typ,
    m_flow_nominal=mChiWatHp_flow_nominal,
    dpValve_nominal=dpValveChiWat_nominal,
    dpFixed_nominal=dpFixedChiWat_nominal)
    "Heat pump outlet CHW isolation valve parameters"
  // dpFixed_nominal only applied to inlet valves if there is no outlet valve.
  final parameter Buildings.Templates.Components.Data.Valve datValChiWatHpInlIso[nHp](
    each typ=typ,
    m_flow_nominal=mChiWatHp_flow_nominal,
    dpValve_nominal=dpValveChiWat_nominal,
    dpFixed_nominal=if not have_valHpOutIso then dpFixedChiWat_nominal else fill(0, nHp))
    "Heat pump inlet CHW isolation valve parameters"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  parameter Modelica.Units.SI.Time tau=10
    "Time constant at nominal flow"
  parameter Boolean allowFlowReversal=true
    "Set to false to simplify equations, assuming, but not enforcing, no flow reversal"
  parameter Boolean use_strokeTime=energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState
    "Set to true to continuously open and close valve"
  parameter Modelica.Units.SI.Time strokeTime=120
    "Time needed to open or close valve"
  parameter Modelica.Blocks.Types.Init init=Modelica.Blocks.Types.Init.InitialOutput
    "Type of initialization (no init/steady state/initial state/initial output)"
  parameter Real y_start=1
    "Initial position of actuator"
  parameter Boolean from_dp=true
    "= true, use m_flow = f(dp) else dp = f(m_flow)"
  parameter Boolean linearized=false
    "= true, use linear relation between m_flow and dp for any flow rate"
  Modelica.Fluid.Interfaces.FluidPort_b port_bChiWat(
    redeclare final package Medium=Medium,
    m_flow(
      max=if allowFlowReversal then + Modelica.Constants.inf else 0),
    h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    if have_chiWat
    "CHW supply (to primary loop)"
  Modelica.Fluid.Interfaces.FluidPort_a port_aChiWat(
    redeclare final package Medium=Medium,
    m_flow(
      min=if allowFlowReversal then - Modelica.Constants.inf else 0),
    h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    if have_chiWat
    "CHW return (from primary loop)"
  Modelica.Fluid.Interfaces.FluidPort_b port_bHeaWat(
    redeclare final package Medium=Medium,
    m_flow(
      max=if allowFlowReversal then + Modelica.Constants.inf else 0),
    h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    "HW supply (to primary loop)"
  Modelica.Fluid.Interfaces.FluidPort_a port_aHeaWat(
    redeclare final package Medium=Medium,
    m_flow(
      min=if allowFlowReversal then - Modelica.Constants.inf else 0),
    h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    "HW return (from primary loop)"
  Modelica.Fluid.Interfaces.FluidPorts_b ports_bChiHeaWatHp[nHp](
    redeclare each final package Medium=Medium,
    each m_flow(
      max=if allowFlowReversal then + Modelica.Constants.inf else 0),
    each h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    "CHW/HW return (HP entering)"
  Modelica.Fluid.Interfaces.FluidPorts_a ports_aChiHeaWatHp[nHp](
    redeclare each final package Medium=Medium,
    each m_flow(
      min=if allowFlowReversal then - Modelica.Constants.inf else 0),
    each h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    if not have_pumChiWatPriDed
    "CHW/HW supply (HP leaving)"
  Modelica.Fluid.Interfaces.FluidPorts_a ports_aHeaWatHp[nHp](
    redeclare each final package Medium=Medium,
    each m_flow(
      min=if allowFlowReversal then - Modelica.Constants.inf else 0),
    each h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    if have_pumChiWatPriDed
    "HW supply (HP leaving)"
  Modelica.Fluid.Interfaces.FluidPorts_a ports_aChiWatHp[nHp](
    redeclare each final package Medium=Medium,
    each m_flow(
      min=if allowFlowReversal then - Modelica.Constants.inf else 0),
    each h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    if have_pumChiWatPriDed
    "CHW supply (HP leaving)"
  Buildings.Templates.Plants.HeatPumps.Interfaces.Bus bus
    "Plant control bus"
  Buildings.Templates.Components.Actuators.Valve valHeaWatHpOutIso[nHp](
    redeclare each final package Medium=Medium,
    final dat=datValHeaWatHpOutIso,
    each final typ=typ,
    each final use_strokeTime=use_strokeTime,
    each final strokeTime=strokeTime,
    each final init=init,
    each final y_start=y_start,
    each final from_dp=from_dp,
    each final linearized=linearized)
    if have_valHpOutIso
    "HP outlet HW isolation valve"
  Buildings.Templates.Components.Actuators.Valve valChiWatHpOutIso[nHp](
    redeclare each final package Medium=Medium,
    final dat=datValChiWatHpOutIso,
    each final typ=typ,
    each final use_strokeTime=use_strokeTime,
    each final strokeTime=strokeTime,
    each final init=init,
    each final y_start=y_start,
    each final from_dp=from_dp,
    each final linearized=linearized)
    if have_valHpOutIso and have_chiWat
    "HP outlet CHW isolation valve"
  Buildings.Templates.Components.Actuators.Valve valHeaWatHpInlIso[nHp](
    redeclare each final package Medium=Medium,
    final dat=datValHeaWatHpInlIso,
    each final typ=typ,
    each final use_strokeTime=use_strokeTime,
    each final strokeTime=strokeTime,
    each final init=init,
    each final y_start=y_start,
    each final from_dp=from_dp,
    each final linearized=linearized)
    if have_valHpInlIso
    "HP inlet HW isolation valve"
  Buildings.Templates.Components.Actuators.Valve valChiWatHpInlIso[nHp](
    redeclare each final package Medium=Medium,
    final dat=datValChiWatHpInlIso,
    each final typ=typ,
    each final use_strokeTime=use_strokeTime,
    each final strokeTime=strokeTime,
    each final init=init,
    each final y_start=y_start,
    each final from_dp=from_dp,
    each final linearized=linearized)
    if have_valHpInlIso and have_chiWat
    "HP inlet CHW isolation valve"
  Buildings.Templates.Components.Routing.PassThroughFluid pasHeaWatHpOut[nHp](
    redeclare each final package Medium=Medium)
    if not have_valHpOutIso
    "Direct fluid pass-through"
  Buildings.Templates.Components.Routing.PassThroughFluid pasChiWatHpOut[nHp](
    redeclare each final package Medium=Medium)
    if not have_valHpOutIso and have_chiWat
    "Direct fluid pass-through"
  Fluid.Delays.DelayFirstOrder junHeaWatSup(
    redeclare final package Medium=Medium,
    final tau=tau,
    final m_flow_nominal=sum(mHeaWatHp_flow_nominal),
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final prescribedHeatFlowRate=false,
    final nPorts=nHp + 1)
    "Fluid volume at junction"
  Fluid.Delays.DelayFirstOrder junChiWatSup(
    redeclare final package Medium=Medium,
    final tau=tau,
    final m_flow_nominal=sum(mChiWatHp_flow_nominal),
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final prescribedHeatFlowRate=false,
    final nPorts=nHp + 1)
    if have_chiWat
    "Fluid volume at junction"
  Fluid.Delays.DelayFirstOrder junHeaWatRet(
    redeclare final package Medium=Medium,
    final tau=tau,
    final m_flow_nominal=sum(mHeaWatHp_flow_nominal),
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final prescribedHeatFlowRate=false,
    final nPorts=nHp + 1)
    "Fluid volume at junction"
  /*
  HW pressure drop computed in this component in the absence of isolation valves
  at both inlet and outlet.
  */
    Fluid.FixedResistances.PressureDrop pasHeaWatHpInl[nHp](
    redeclare each final package Medium=Medium,
    final m_flow_nominal=mHeaWatHp_flow_nominal,
    final dp_nominal=if not have_valHpInlIso and not have_valHpOutIso then dpFixedHeaWat_nominal
      else fill(0, nHp))
    if not have_valHpInlIso
    "Direct fluid pass-through with optional fluid resistance"
  /*
  CHW pressure drop computed in this component in the absence of isolation valves
  at both inlet and outlet.
  */
    Fluid.FixedResistances.PressureDrop pasChiWatHpInl[nHp](
    redeclare each final package Medium=Medium,
    final m_flow_nominal=mChiWatHp_flow_nominal,
    final dp_nominal=if not have_valHpInlIso and not have_valHpOutIso then dpFixedChiWat_nominal
      else fill(0, nHp))
    if not have_valHpInlIso and have_chiWat
    "Direct fluid pass-through with optional fluid resistance"
  Fluid.Delays.DelayFirstOrder junChiWatRet(
    redeclare final package Medium=Medium,
    final tau=tau,
    final m_flow_nominal=sum(mChiWatHp_flow_nominal),
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final prescribedHeatFlowRate=false,
    final nPorts=nHp + 1)
    if have_chiWat
    "Fluid volume at junction"
protected
  Buildings.Templates.Components.Interfaces.Bus busValHeaWatHpInlIso[nHp]
    if have_valHpInlIso
    "Heat pump inlet HW isolation valve control bus"
  Buildings.Templates.Components.Interfaces.Bus busValHeaWatHpOutIso[nHp]
    if have_valHpOutIso
    "Heat pump outlet HW isolation valve control bus"
  Buildings.Templates.Components.Interfaces.Bus busValChiWatHpInlIso[nHp]
    if have_chiWat and have_valHpInlIso
    "Heat pump inlet CHW isolation valve control bus"
  Buildings.Templates.Components.Interfaces.Bus busValChiWatHpOutIso[nHp]
    if have_chiWat and have_valHpOutIso
    "Heat pump outlet CHW isolation valve control bus"
equation
  connect(bus.valHeaWatHpInlIso, busValHeaWatHpInlIso)
  connect(bus.valHeaWatHpOutIso, busValHeaWatHpOutIso)
  connect(bus.valChiWatHpInlIso, busValChiWatHpInlIso)
  connect(bus.valChiWatHpOutIso, busValChiWatHpOutIso)
  connect(ports_aHeaWatHp, valHeaWatHpOutIso.port_a)
  connect(ports_aChiHeaWatHp, valHeaWatHpOutIso.port_a)
  connect(ports_aChiHeaWatHp, valChiWatHpOutIso.port_a)
  connect(ports_aChiWatHp, valChiWatHpOutIso.port_a)
  connect(ports_aHeaWatHp, pasHeaWatHpOut.port_a)
  connect(ports_aChiHeaWatHp, pasHeaWatHpOut.port_a)
  connect(ports_aChiHeaWatHp, pasChiWatHpOut.port_a)
  connect(ports_aChiWatHp, pasChiWatHpOut.port_a)
  connect(valHeaWatHpOutIso.port_b, junHeaWatSup.ports[1:nHp])
  connect(pasHeaWatHpOut.port_b, junHeaWatSup.ports[1:nHp])
  connect(junHeaWatSup.ports[nHp + 1], port_bHeaWat)
  connect(valChiWatHpOutIso.port_b, junChiWatSup.ports[1:nHp])
  connect(pasChiWatHpOut.port_b, junChiWatSup.ports[1:nHp])
  connect(port_bChiWat, junChiWatSup.ports[nHp + 1])
  connect(port_aHeaWat, junHeaWatRet.ports[nHp + 1])
  connect(junHeaWatRet.ports[1:nHp], valHeaWatHpInlIso.port_a)
  connect(pasHeaWatHpInl.port_a, junHeaWatRet.ports[1:nHp])
  connect(port_aChiWat, junChiWatRet.ports[nHp + 1])
  connect(valChiWatHpInlIso.port_a, junChiWatRet.ports[1:nHp])
  connect(pasChiWatHpInl.port_a, junChiWatRet.ports[1:nHp])
  connect(pasHeaWatHpInl.port_b, ports_bChiHeaWatHp)
  connect(pasChiWatHpInl.port_b, ports_bChiHeaWatHp)
  connect(busValHeaWatHpInlIso, valHeaWatHpInlIso.bus)
  connect(busValChiWatHpInlIso, valChiWatHpInlIso.bus)
  connect(busValChiWatHpOutIso, valChiWatHpOutIso.bus)
  connect(busValHeaWatHpOutIso, valHeaWatHpOutIso.bus)

  connect(valHeaWatHpInlIso.port_b, ports_bChiHeaWatHp)
  connect(valChiWatHpInlIso.port_b, ports_bChiHeaWatHp)
end ValvesIsolation;


Controller for AWHP plant. This class implements the sequence of operation for plants with
air-to-water heat pumps.
It is based on the controller

Buildings.Templates.Plants.Controls.HeatPumps.AirToWater.

within Buildings.Templates.Plants.HeatPumps.Components.Controls;
model AirToWater
  "Controller for AWHP plant"
  extends
    Buildings.Templates.Plants.HeatPumps.Components.Interfaces.PartialController(
    final typ=Buildings.Templates.Plants.HeatPumps.Types.Controller.AirToWater);
  final parameter Real staEqu[:, nHp](
    each final max=1,
    each final min=0,
    each final unit="1")=dat.staEqu
    "Staging matrix – Equipment required for each stage"
  final parameter Integer nSta(
    final min=1)=size(staEqu, 1)
    "Number of stages"
  final parameter Integer idxEquAlt[ctl.nEquAlt]=Modelica.Math.BooleanVectors.index(
    {Modelica.Math.BooleanVectors.anyTrue({
      nHp==1 or staEqu[i,j] > 0 and staEqu[i,j] < 1 for i in 1:nSta})
      for j in 1:nHp})
    "Indices of lead/lag alternate equipment"
  Buildings.Templates.Plants.Controls.HeatPumps.AirToWater ctl(
    final is_priOnl=cfg.typDis==Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only,
    final have_hrc_select=cfg.have_hrc,
    final TChiWatSupSet_max=dat.TChiWatSupSet_max,
    final TChiWatSup_nominal=dat.TChiWatSup_nominal,
    final THeaWatSupSet_min=dat.THeaWatSupSet_min,
    final THeaWatSup_nominal=dat.THeaWatSup_nominal,
    final TOutChiWatLck=dat.TOutChiWatLck,
    final TOutHeaWatLck=dat.TOutHeaWatLck,
    final VChiWatHp_flow_min=fill(dat.VChiWatHp_flow_min, cfg.nHp),
    final VChiWatHp_flow_nominal=fill(dat.VChiWatHp_flow_nominal, cfg.nHp),
    final VChiWatPri_flow_nominal=dat.VChiWatPri_flow_nominal,
    final VChiWatSec_flow_nominal=dat.VChiWatSec_flow_nominal,
    final VHeaWatHp_flow_min=fill(dat.VHeaWatHp_flow_min, cfg.nHp),
    final VHeaWatHp_flow_nominal=fill(dat.VHeaWatHp_flow_nominal, cfg.nHp),
    final VHeaWatPri_flow_nominal=dat.VHeaWatPri_flow_nominal,
    final VHeaWatSec_flow_nominal=dat.VHeaWatSec_flow_nominal,
    final capCooHp_nominal=fill(dat.capCooHp_nominal, cfg.nHp),
    final capHeaHp_nominal=fill(dat.capHeaHp_nominal, cfg.nHp),
    final cp_default=if cfg.have_heaWat then cfg.cpHeaWat_default else cfg.cpChiWat_default,
    final dpChiWatRemSet_max=dat.dpChiWatRemSet_max,
    final dpChiWatRemSet_min=dat.dpChiWatRemSet_min,
    final dpHeaWatRemSet_max=dat.dpHeaWatRemSet_max,
    final dpHeaWatRemSet_min=dat.dpHeaWatRemSet_min,
    final capCooHrc_min=dat.capCooHrc_min,
    final capHeaHrc_min=dat.capHeaHrc_min,
    final COPHeaHrc_nominal=dat.COPHeaHrc_nominal,
    final TChiWatSupHrc_min=dat.TChiWatSupHrc_min,
    final THeaWatSupHrc_max=dat.THeaWatSupHrc_max,
    final have_chiWat=cfg.have_chiWat,
    final have_heaWat=cfg.have_heaWat,
    final have_inpSch=have_inpSch,
    final have_pumChiWatPriDed_select=cfg.have_pumChiWatPriDed,
    final have_pumPriHdr=cfg.typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Headered,
    final have_pumHeaWatPriVar_select=cfg.have_pumHeaWatPriVar,
    final have_pumChiWatPriVar_select=cfg.have_pumChiWatPriVar,
    final have_senDpChiWatRemWir=cfg.have_senDpChiWatRemWir,
    final have_senDpHeaWatRemWir=cfg.have_senDpHeaWatRemWir,
    final have_senTChiWatPriRet_select=have_senTChiWatPriRet_select,
    final have_senTChiWatSecRet_select=have_senTChiWatSecRet_select,
    final have_senTHeaWatPriRet_select=have_senTHeaWatPriRet_select,
    final have_senTHeaWatSecRet_select=have_senTHeaWatSecRet_select,
    final have_senVChiWatPri_select=have_senVChiWatPri_select,
    final have_senVHeaWatPri_select=have_senVHeaWatPri_select,
    final have_valHpInlIso=cfg.have_valHpInlIso,
    final have_valHpOutIso=cfg.have_valHpOutIso,
    final idxEquAlt=idxEquAlt,
    final nHp=cfg.nHp,
    final nPumChiWatPri=cfg.nPumChiWatPri,
    final nPumChiWatSec=cfg.nPumChiWatSec,
    final nPumHeaWatPri=cfg.nPumHeaWatPri,
    final nPumHeaWatSec=cfg.nPumHeaWatSec,
    final nSenDpChiWatRem=nSenDpChiWatRem,
    final nSenDpHeaWatRem=nSenDpHeaWatRem,
    final plrSta=dat.plrSta,
    final rho_default=if cfg.have_heaWat then cfg.rhoHeaWat_default else cfg.rhoChiWat_default,
    final schCoo=dat.schCoo,
    final schHea=dat.schHea,
    final staEqu=dat.staEqu,
    final yPumChiWatPri_min=dat.yPumChiWatPri_min,
    yPumChiWatPriSet=dat.yPumChiWatPriSet,
    final yPumChiWatSec_min=dat.yPumChiWatSec_min,
    final yPumHeaWatPri_min=dat.yPumHeaWatPri_min,
    yPumHeaWatPriSet=dat.yPumHeaWatPriSet,
    final yPumHeaWatSec_min=dat.yPumHeaWatSec_min)
    "Plant controller"
  Buildings.Controls.OBC.CDL.Integers.MultiSum reqPlaHeaWatAirHan(
    final nin=nAirHan) if cfg.have_heaWat "Sum of HW plant requests from AHU"
  Buildings.Controls.OBC.CDL.Integers.MultiSum reqPlaHeaWatEquZon(
    final nin=nEquZon) if cfg.have_heaWat
    "Sum of HW plant requests from zone equipment"
  Buildings.Controls.OBC.CDL.Integers.MultiSum reqResHeaWatAirHan(nin=1)
    if cfg.have_heaWat "Sum of HW reset requests from AHU"
  Buildings.Controls.OBC.CDL.Integers.MultiSum reqResHeaWatEquZon(
    final nin=nEquZon) if cfg.have_heaWat
    "Sum of HW reset requests from zone equipment"
  Buildings.Controls.OBC.CDL.Integers.MultiSum reqResChiWatAirHan(final nin=
        nAirHan) if cfg.have_chiWat "Sum of CHW reset requests from AHU"
  Buildings.Controls.OBC.CDL.Integers.MultiSum reqPlaChiWatEquZon(final nin=
        nEquZon) if cfg.have_chiWat
    "Sum of CHW plant requests from zone equipment"
  Buildings.Controls.OBC.CDL.Integers.MultiSum reqResChiWatEquZon(final nin=
        nEquZon) if cfg.have_chiWat
    "Sum of CHW reset requests from zone equipment"
  Buildings.Controls.OBC.CDL.Integers.MultiSum reqPlaChiWatAirHan(final nin=
        nAirHan) if cfg.have_chiWat "Sum of CHW plant requests from AHU"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderInteger phReqPlaHeaWatAirHan(
    final have_inp=cfg.have_heaWat,
    final u_internal=0)
    "Placeholder value if signal is not available"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderInteger phReqPlaChiWatAirHan(final
      have_inp=cfg.have_chiWat, final u_internal=0)
    "Placeholder value if signal is not available"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderInteger phReqResHeaWatAirHan(final
      have_inp=cfg.have_heaWat, final u_internal=0)
    "Placeholder value if signal is not available"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderInteger phReqResChiWatAirHan(final
      have_inp=cfg.have_chiWat, final u_internal=0)
    "Placeholder value if signal is not available"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderInteger phReqPlaHeaWatEquZon(final
      have_inp=cfg.have_heaWat, final u_internal=0)
    "Placeholder value if signal is not available"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderInteger phReqPlaChiWatEquZon(final
      have_inp=cfg.have_chiWat, final u_internal=0)
    "Placeholder value if signal is not available"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderInteger phReqResHeaWatEquZon(final
      have_inp=cfg.have_heaWat, final u_internal=0)
    "Placeholder value if signal is not available"
  Buildings.Templates.Plants.Controls.Utilities.PlaceholderInteger phReqResChiWatEquZon(final
      have_inp=cfg.have_chiWat, final u_internal=0)
    "Placeholder value if signal is not available"
  Buildings.Controls.OBC.CDL.Integers.Add reqPlaHeaWat
    "Sum of HW plant requests of all loads served"
  Buildings.Controls.OBC.CDL.Integers.Add reqPlaChiWat
    "Sum of CHW plant requests of all loads served"
  Buildings.Controls.OBC.CDL.Integers.Add reqResHeaWat
    "Sum of HW reset requests of all loads served"
  Buildings.Controls.OBC.CDL.Integers.Add reqResChiWat
    "Sum of CHW reset requests of all loads served"
  Buildings.Templates.Plants.Controls.Pumps.Generic.ResetLocalDifferentialPressure
    resDpHeaWatLoc[nSenDpHeaWatRem](
    dpLocSet_min=fill(dat.dpHeaWatLocSet_min, nSenDpHeaWatRem),
    dpLocSet_max=fill(dat.dpHeaWatLocSet_max, nSenDpHeaWatRem))
    if cfg.have_heaWat and not have_senDpHeaWatRemWir
    "Local HW DP reset"
  Buildings.Templates.Plants.Controls.Pumps.Generic.ResetLocalDifferentialPressure
    resDpChiWatLoc[nSenDpChiWatRem](
    dpLocSet_min=fill(dat.dpChiWatLocSet_min, nSenDpChiWatRem),
    dpLocSet_max=fill(dat.dpChiWatLocSet_max, nSenDpChiWatRem))
    if cfg.have_chiWat and not have_senDpChiWatRemWir
    "Local CHW DP reset"
equation
  /* Control point connection - start */
  // Inputs from plant control bus
  connect(bus.TChiWatPriRet, ctl.TChiWatPriRet);
  connect(bus.TChiWatPriSup, ctl.TChiWatPriSup);
  connect(bus.TChiWatSecRet, ctl.TChiWatSecRet);
  connect(bus.TChiWatSecSup, ctl.TChiWatSecSup);
  connect(bus.THeaWatPriRet, ctl.THeaWatPriRet);
  connect(bus.THeaWatPriSup, ctl.THeaWatPriSup);
  connect(bus.THeaWatSecRet, ctl.THeaWatSecRet);
  connect(bus.THeaWatSecSup, ctl.THeaWatSecSup);
  connect(bus.TOut, ctl.TOut);
  connect(bus.VChiWatPri_flow, ctl.VChiWatPri_flow);
  connect(bus.VChiWatSec_flow, ctl.VChiWatSec_flow);
  connect(bus.VHeaWatPri_flow, ctl.VHeaWatPri_flow);
  connect(bus.VHeaWatSec_flow, ctl.VHeaWatSec_flow);
  connect(bus.dpChiWatLoc, ctl.dpChiWatLoc);
  connect(bus.dpChiWatLocSet, ctl.dpChiWatLocSet);
  connect(bus.dpChiWatRem, ctl.dpChiWatRem);
  connect(bus.dpChiWatRem, resDpChiWatLoc.dpRem);
  connect(bus.dpHeaWatLoc, ctl.dpHeaWatLoc);
  connect(bus.dpHeaWatLocSet, ctl.dpHeaWatLocSet);
  connect(bus.dpHeaWatRem, ctl.dpHeaWatRem);
  connect(bus.dpHeaWatRem, resDpHeaWatLoc.dpRem);
  connect(busHp.y1_actual, ctl.u1Hp_actual);
  connect(busPumChiWatPri.y1_actual, ctl.u1PumChiWatPri_actual);
  connect(busPumChiWatSec.y1_actual, ctl.u1PumChiWatSec_actual);
  connect(busPumHeaWatPri.y1_actual, ctl.u1PumHeaWatPri_actual);
  connect(busPumHeaWatSec.y1_actual, ctl.u1PumHeaWatSec_actual);
  connect(bus.u1SchCoo, ctl.u1SchCoo);
  connect(bus.u1SchHea, ctl.u1SchHea);
  connect(busHrc.y1_actual, ctl.u1Hrc_actual);
  connect(bus.TChiWatRetUpsHrc, ctl.TChiWatRetUpsHrc);
  connect(bus.THeaWatRetUpsHrc, ctl.THeaWatRetUpsHrc);
  // Outputs to plant control bus
  connect(ctl.TSupSet, busHp.TSet);
  connect(ctl.TChiWatSupSet, bus.TChiWatSupSet);
  connect(ctl.THeaWatSupSet, bus.THeaWatSupSet);
  connect(ctl.dpChiWatRemSet, bus.dpChiWatRemSet);
  connect(ctl.dpHeaWatRemSet, bus.dpHeaWatRemSet);
  connect(ctl.y1HeaHp, busHp.y1Hea);
  connect(ctl.y1Hp, busHp.y1);
  connect(ctl.y1PumChiWatPri, busPumChiWatPri.y1);
  connect(ctl.y1PumChiWatSec, busPumChiWatSec.y1);
  connect(ctl.y1PumHeaWatPri, busPumHeaWatPri.y1);
  connect(ctl.y1PumHeaWatSec, busPumHeaWatSec.y1);
  connect(ctl.y1ValChiWatHpInlIso, busValChiWatHpInlIso.y1);
  connect(ctl.y1ValChiWatHpOutIso, busValChiWatHpOutIso.y1);
  connect(ctl.y1ValHeaWatHpInlIso, busValHeaWatHpInlIso.y1);
  connect(ctl.y1ValHeaWatHpOutIso, busValHeaWatHpOutIso.y1);
  connect(ctl.yValHeaWatMinByp, busValHeaWatMinByp.y);
  connect(ctl.yValChiWatMinByp, busValChiWatMinByp.y);
  connect(ctl.yPumChiWatPriDed, busPumChiWatPri.y);
  connect(ctl.yPumChiWatPriHdr, busPumChiWatPri.y);
  connect(ctl.yPumChiWatSec, busPumChiWatSec.y);
  connect(ctl.yPumHeaWatPriDed, busPumHeaWatPri.y);
  connect(ctl.yPumHeaWatPriHdr, busPumHeaWatPri.y);
  connect(ctl.yPumHeaWatSec, busPumHeaWatSec.y);
  connect(ctl.y1Hrc, busHrc.y1);
  connect(ctl.y1CooHrc, busHrc.y1Coo);
  connect(ctl.TSupSetHrc, busHrc.TSupSet);
  connect(ctl.y1PumChiWatHrc, busPumChiWatHrc.y1);
  connect(ctl.y1PumHeaWatHrc, busPumHeaWatHrc.y1);
  /* Control point connection - stop */
  connect(busAirHan.reqResChiWat, reqResChiWatAirHan.u)
  connect(busEquZon.reqPlaHeaWat, reqPlaHeaWatEquZon.u)
  connect(busEquZon.reqResHeaWat, reqResHeaWatEquZon.u)
  connect(busEquZon.reqPlaChiWat, reqPlaChiWatEquZon.u)
  connect(busEquZon.reqResChiWat, reqResChiWatEquZon.u)
  connect(busAirHan.reqPlaChiWat, reqPlaChiWatAirHan.u)
  connect(busAirHan.reqPlaHeaWat, reqPlaHeaWatAirHan.u)
  connect(busAirHan.reqResHeaWat, reqResHeaWatAirHan.u[1:1])
  connect(reqPlaHeaWatAirHan.y, phReqPlaHeaWatAirHan.u)
  connect(reqPlaChiWatAirHan.y, phReqPlaChiWatAirHan.u)
  connect(reqResHeaWatAirHan.y, phReqResHeaWatAirHan.u)
  connect(reqResChiWatAirHan.y, phReqResChiWatAirHan.u)
  connect(reqPlaHeaWatEquZon.y, phReqPlaHeaWatEquZon.u)
  connect(reqPlaChiWatEquZon.y, phReqPlaChiWatEquZon.u)
  connect(reqResChiWatEquZon.y, phReqResChiWatEquZon.u)
  connect(reqResHeaWatEquZon.y, phReqResHeaWatEquZon.u)
  connect(phReqPlaHeaWatAirHan.y, reqPlaHeaWat.u1)
  connect(phReqPlaHeaWatEquZon.y, reqPlaHeaWat.u2)
  connect(phReqPlaChiWatAirHan.y, reqPlaChiWat.u1)
  connect(phReqPlaChiWatEquZon.y, reqPlaChiWat.u2)
  connect(phReqResHeaWatAirHan.y, reqResHeaWat.u1)
  connect(phReqResChiWatAirHan.y, reqResChiWat.u1)
  connect(phReqResHeaWatEquZon.y, reqResHeaWat.u2)
  connect(phReqResChiWatEquZon.y, reqResChiWat.u2)
  connect(reqPlaHeaWat.y, ctl.nReqPlaHeaWat)
  connect(reqPlaChiWat.y, ctl.nReqPlaChiWat)
  connect(reqResHeaWat.y,ctl.nReqResHeaWat)
  connect(reqResChiWat.y,ctl.nReqResChiWat)
  connect(resDpHeaWatLoc.dpLocSet, ctl.dpHeaWatLocSet)
  connect(resDpChiWatLoc.dpLocSet, ctl.dpChiWatLocSet)
  connect(ctl.dpChiWatRemSet, resDpChiWatLoc.dpRemSet)
  connect(ctl.dpHeaWatRemSet, resDpHeaWatLoc.dpRemSet)
end AirToWater;


Open-loop controller. This is an open loop controller providing control inputs
for the plant model

Buildings.Templates.Plants.HeatPumps.AirToWater.
It is only used for testing purposes.

within Buildings.Templates.Plants.HeatPumps.Components.Controls;
block OpenLoop
  "Open-loop controller"
  extends
    Buildings.Templates.Plants.HeatPumps.Components.Interfaces.PartialController(
    final typ=Buildings.Templates.Plants.HeatPumps.Types.Controller.OpenLoop);
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSupSet[nHp](
    y(each final unit="K",
      each displayUnit="degC"),
    each k=Buildings.Templates.Data.Defaults.THeaWatSupMed)
    "Heat pump HW supply temperature set point"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSupSet[nHp](
    y(each final unit="K",
      each displayUnit="degC"),
    each k=Buildings.Templates.Data.Defaults.TChiWatSup)
    "Heat pump CHW supply temperature set point"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1ValHeaWatHpInlIso[nHp](
    each table=[
      0, 0;
      1, 1;
      3, 0;
      5, 0],
    each timeScale=1000,
    each period=5000)
    if cfg.have_heaWat and cfg.have_valHpInlIso
    "Heat pump inlet HW isolation valve opening signal"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1ValHeaWatHpOutIso[nHp](
    each table=[
      0, 0;
      1, 1;
      3, 0;
      5, 0],
    each timeScale=1000,
    each period=5000)
    if cfg.have_heaWat and cfg.have_valHpOutIso
    "Heat pump outlet HW isolation valve opening signal"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1ValChiWatHpInlIso[nHp](
    each table=[
      0, 0;
      3.1, 1;
      5, 0],
    each timeScale=1000,
    each period=5000)
    if cfg.have_chiWat and cfg.have_valHpInlIso
    "Heat pump inlet CHW isolation valve opening signal"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1ValChiWatHpOutIso[nHp](
    each table=[
      0, 0;
      3.1, 1;
      5, 0],
    each timeScale=1000,
    each period=5000)
    if cfg.have_chiWat and cfg.have_valHpOutIso
    "Heat pump outlet CHW isolation valve opening signal"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1Hp[nHp](
    each table=[
      0, 0;
      1, 0;
      1, 1;
      5, 1],
    each timeScale=1000,
    each period=5000)
    "Heat pump start/stop command"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1HeaHp[nHp](
    each table=[
      0, 1;
      3, 0;
      5, 0],
    each timeScale=1000,
    each period=5000)
    if cfg.is_rev
    "Heat pump heating mode command"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1PumHeaWatPri[cfg.nPumHeaWatPri](
    each table=if cfg.have_pumChiWatPriDed or not cfg.have_chiWat then
                                                                      [
      0, 0;
      1, 1;
      3, 0;
      5, 0] else
                [
      0, 0;
      1, 1;
      3, 0;
      3.1, 1;
      5, 0],
    each timeScale=1000,
    each period=5000)
    if cfg.have_heaWat
    "Primary CHW pump start/stop command"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1PumChiWatPri[cfg.nPumChiWatPri](
    each table=[
      0, 0;
      3.1, 1;
      5, 0],
    each timeScale=1000,
    each period=5000)
    if cfg.have_pumChiWatPriDed
    "Primary CHW pump start/stop command"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1PumHeaWatSec[cfg.nPumHeaWatSec](
    each table=[
      0, 0;
      1, 1;
      3, 0;
      5, 0],
    each timeScale=1000,
    each period=5000)
    if cfg.typPumHeaWatSec <> Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None
    "Secondary HW pump start/stop command"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1PumChiWatSec[cfg.nPumChiWatSec](
    each table=[
      0, 0;
      3, 1;
      5, 1],
    each timeScale=1000,
    each period=5000)
    if cfg.typPumChiWatSec <> Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None
    "Secondary CHW pump start/stop command"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yPumHeaWatSec(
    k=1)
    if cfg.typPumHeaWatSec <> Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None
    "Secondary HW pump speed signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yPumChiWatSec(
    k=1)
    if cfg.typPumChiWatSec <> Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None
    "Secondary CHW pump speed signal"
  Buildings.Controls.OBC.CDL.Reals.Switch TSet[nHp](
    y(each final unit="K",
      each displayUnit="degC"))
    "Active supply temperature setpoint"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant tru[nHp](
    each final k=true)
    if not cfg.is_rev
    "Constant"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yPumHeaWatPriHdr(k=1)
    if cfg.have_heaWat and cfg.have_pumHeaWatPriVar and
      cfg.typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Headered
    "Headered primary HW pump speed signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yPumChiWatPriHdr(k=1)
    if cfg.have_chiWat and cfg.have_pumHeaWatPriVar and
      cfg.typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Headered
    "Headered primary CHW pump speed signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yPumHeaWatPriDed[cfg.nPumHeaWatPri](
     each k=1) if cfg.have_heaWat and cfg.have_pumHeaWatPriVar and
      cfg.typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Dedicated
    "Dedicated primary HW pump speed signal"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yPumChiWatPriDed[cfg.nPumChiWatPri](
     each k=1) if cfg.have_pumChiWatPriDed and cfg.have_pumHeaWatPriVar
    "Dedicated primary CHW pump speed signal"
equation
  /* Control point connection - start */
  connect(y1PumHeaWatPri.y[1], busPumHeaWatPri.y1);
  connect(yPumHeaWatPriHdr.y, busPumHeaWatPri.y);
  connect(yPumHeaWatPriDed.y, busPumHeaWatPri.y);
  connect(y1PumHeaWatSec.y[1], busPumHeaWatSec.y1);
  connect(yPumHeaWatSec.y, busPumHeaWatSec.y);
  connect(y1ValHeaWatHpInlIso.y[1], busValHeaWatHpInlIso.y1);
  connect(y1ValHeaWatHpOutIso.y[1], busValHeaWatHpOutIso.y1);
  connect(yPumChiWatSec.y, busPumChiWatSec.y);
  connect(y1ValChiWatHpOutIso.y[1], busValChiWatHpOutIso.y1);
  connect(y1PumChiWatPri.y[1], busPumChiWatPri.y1);
  connect(yPumChiWatPriHdr.y, busPumChiWatPri.y);
  connect(yPumChiWatPriDed.y, busPumChiWatPri.y);
  connect(y1ValChiWatHpInlIso.y[1], busValChiWatHpInlIso.y1);
  connect(y1PumChiWatSec.y[1], busPumChiWatSec.y1);
  connect(y1Hp.y[1], busHp.y1);
  connect(y1HeaHp.y[1], busHp.y1Hea);
  connect(TSet.y, busHp.TSet);
  /* Control point connection - stop */
                                       connect(TChiWatSupSet.y, TSet.u3)
  connect(THeaWatSupSet.y, TSet.u1)
  connect(y1HeaHp.y[1], TSet.u2)
  connect(tru.y, TSet.u2)
end OpenLoop;


Controllers

within Buildings.Templates.Plants.HeatPumps.Components;
package Controls "Controllers"
  extends Modelica.Icons.VariantsPackage;
end Controls;


within Buildings.Templates.Plants.HeatPumps.Components;
package Data "Records for design and operating parameters"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Data;