Multiple-configuration damper

within Buildings.Templates.Components.Actuators;
model Damper "Multiple-configuration damper"
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
    final m_flow_nominal=dat.m_flow_nominal)

  parameter Buildings.Templates.Components.Types.Damper typ
    "Equipment type"

  parameter Buildings.Templates.Components.Data.Damper dat(final typ=typ)
    "Design and operating parameters"

  final parameter Modelica.Units.SI.PressureDifference dp_nominal=
    dat.dp_nominal
    "Damper pressure drop";

  parameter Boolean use_strokeTime=true
    "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 = false
    "= 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"

  parameter Buildings.Templates.Components.Types.DamperBlades typBla=
    if typ==Buildings.Templates.Components.Types.Damper.TwoPosition then
      Buildings.Templates.Components.Types.DamperBlades.Opposed
    elseif typ==Buildings.Templates.Components.Types.Damper.PressureIndependent then
      Buildings.Templates.Components.Types.DamperBlades.VAV
    else Buildings.Templates.Components.Types.DamperBlades.Parallel
    "Type of blades"
  parameter Integer text_rotation = 0
    "Text rotation angle in icon layer"
  parameter Boolean text_flip = false
    "True to flip text horizontally in icon layer"

  Buildings.Templates.Components.Interfaces.Bus bus
    if typ <> Buildings.Templates.Components.Types.Damper.None
    "Control bus"

  Buildings.Fluid.Actuators.Dampers.Exponential exp(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final dpDamper_nominal=dp_nominal,
    final dpFixed_nominal=dat.dpFixed_nominal,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=init,
    final y_start=y_start,
    final allowFlowReversal=allowFlowReversal,
    final show_T=show_T,
    final from_dp=from_dp,
    final linearized=linearized) if typ == Buildings.Templates.Components.Types.Damper.Modulating
     or typ == Buildings.Templates.Components.Types.Damper.TwoPosition
    "Damper with exponential characteristic"
  Buildings.Fluid.Actuators.Dampers.PressureIndependent ind(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final dpDamper_nominal=dp_nominal,
    final dpFixed_nominal=dat.dpFixed_nominal,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=init,
    final y_start=y_start,
    final allowFlowReversal=allowFlowReversal,
    final show_T=show_T,
    final from_dp=from_dp)
    if typ==Buildings.Templates.Components.Types.Damper.PressureIndependent
    "Pressure independent damper"
  Buildings.Templates.Components.Routing.PassThroughFluid non(
    redeclare final package Medium = Medium)
    if typ==Buildings.Templates.Components.Types.Damper.None
    "No damper"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal y1(final realTrue=1,
      final realFalse=0)
    if typ == Buildings.Templates.Components.Types.Damper.TwoPosition
    "Two-position signal"
  Modelica.Blocks.Routing.RealPassThrough y if typ == Buildings.Templates.Components.Types.Damper.Modulating
     or typ == Buildings.Templates.Components.Types.Damper.PressureIndependent
    "Modulating signal"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold y0_actual(t=0.01, h=0.5E-2)
    if typ == Buildings.Templates.Components.Types.Damper.TwoPosition
    "Closed end switch status"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold y1_actual(t=0.99, h=0.5E-2)
    if typ == Buildings.Templates.Components.Types.Damper.TwoPosition
    "Open end switch status"
  Modelica.Blocks.Routing.RealPassThrough y_actual if typ == Buildings.Templates.Components.Types.Damper.Modulating
     or typ == Buildings.Templates.Components.Types.Damper.PressureIndependent
    "Position feedback"
equation
  /* Control point connection - start */
  connect(y1.y, exp.y);
  connect(y.y, exp.y);
  connect(y_actual.u, exp.y_actual);
  connect(y0_actual.u, exp.y_actual);
  connect(y1_actual.u, exp.y_actual);
  connect(y1.y, ind.y);
  connect(y.y, ind.y);
  connect(y_actual.u, ind.y_actual);
  connect(y0_actual.u, ind.y_actual);
  connect(y1_actual.u, ind.y_actual);
  /* Control point connection - stop */
  connect(port_a, non.port_a)
  connect(non.port_b, port_b)
  connect(port_a,exp. port_a)
  connect(exp.port_b, port_b)
  connect(port_a, ind.port_a)
  connect(ind.port_b, port_b)
  connect(bus.y1, y1.u)
  connect(bus.y, y.u)
  connect(bus.y_actual, y_actual.y)
  connect(bus.y0_actual, y0_actual.y)
  connect(bus.y1_actual, y1_actual.y)
end Damper;


Damper and valve models

within Buildings.Templates.Components;
package Actuators "Damper and valve models"
  extends Modelica.Icons.VariantsPackage;
end Actuators;


Multiple-configuration valve

within Buildings.Templates.Components.Actuators;
model Valve "Multiple-configuration valve"
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
    final m_flow_nominal=dat.m_flow_nominal)

  parameter Buildings.Templates.Components.Types.Valve typ
    "Equipment type"

  // The following proxy parameters are not evaluated when used in Dialog(enable)
  // annotations with Dymola: explicit expressions are required.
  final parameter Boolean is_twoWay=
    typ==Buildings.Templates.Components.Types.Valve.TwoWayModulating
    or typ==Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition
    "Evaluate to true in case of two-way valve"
  final parameter Boolean is_thrWay=
    typ==Buildings.Templates.Components.Types.Valve.ThreeWayModulating
    or typ==Buildings.Templates.Components.Types.Valve.ThreeWayTwoPosition
    "Evaluate to true in case of three-way valve"
  final parameter Boolean is_actTwo=
    typ==Buildings.Templates.Components.Types.Valve.TwoWayTwoPosition
    or typ==Buildings.Templates.Components.Types.Valve.ThreeWayTwoPosition
    "Evaluate to true in case of two-position actuator"
  final parameter Boolean is_actMod=
    typ==Buildings.Templates.Components.Types.Valve.ThreeWayModulating
    or typ==Buildings.Templates.Components.Types.Valve.TwoWayModulating
    "Evaluate to true in case of modulating actuator"

  parameter Buildings.Templates.Components.Types.ValveCharacteristicTwoWay chaTwo=
    if is_actMod then Buildings.Templates.Components.Types.ValveCharacteristicTwoWay.EqualPercentage
    else Buildings.Templates.Components.Types.ValveCharacteristicTwoWay.Linear
    "Flow characteristic"
  parameter Buildings.Templates.Components.Types.ValveCharacteristicThreeWay chaThr=
    if is_actMod then Buildings.Templates.Components.Types.ValveCharacteristicThreeWay.EqualPercentageLinear
    else Buildings.Templates.Components.Types.ValveCharacteristicThreeWay.Linear
    "Flow characteristic"

  replaceable parameter Buildings.Fluid.Actuators.Valves.Data.Generic flowCharacteristics(
    y={0,1},
    phi={0.0001,1})
    "Table with flow characteristics"
  replaceable parameter Buildings.Fluid.Actuators.Valves.Data.Generic flowCharacteristics1(
    y={0,1},
    phi={0.0001,1})
    "Table with flow characteristics for direct flow path at port_1"
  replaceable parameter Buildings.Fluid.Actuators.Valves.Data.Generic flowCharacteristics3(
    y={0,1},
    phi={0.0001,1})
    "Table with flow characteristics for bypass flow path at port_3"
  parameter Real fraK(min=0, max=1) = 1.0
    "Fraction Kv(port_3→port_2)/Kv(port_1→port_2)"

  parameter Buildings.Templates.Components.Data.Valve dat(final typ=typ)
    "Design and operating parameters"

  final parameter Modelica.Units.SI.PressureDifference dpValve_nominal=
    dat.dpValve_nominal
    "Nominal pressure drop of fully open valve";
  final parameter Modelica.Units.SI.PressureDifference dpFixed_nominal=
    dat.dpFixed_nominal
    "Nominal pressure drop of pipes and other equipment in flow leg";
  final parameter Modelica.Units.SI.PressureDifference dpFixedByp_nominal=
    dat.dpFixedByp_nominal
    "Nominal pressure drop in the bypass line";

  parameter Boolean use_strokeTime=true
    "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 Modelica.Units.SI.Time tau=10
    "Time constant at nominal flow"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=
    Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"

  parameter Boolean from_dp = false
    "= 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"

  parameter Integer text_rotation = 0
    "Text rotation angle in icon layer"
  parameter Boolean text_flip = false
    "True to flip text horizontally in icon layer"

  Modelica.Fluid.Interfaces.FluidPort_a portByp_a(
    redeclare final package Medium = Medium,
    p(start=Medium.p_default),
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=Medium.h_default, nominal=Medium.h_default))
    if typ==Buildings.Templates.Components.Types.Valve.ThreeWayTwoPosition or
      typ==Buildings.Templates.Components.Types.Valve.ThreeWayModulating
    "Fluid connector with bypass line"
  Buildings.Templates.Components.Interfaces.Bus bus
    if typ<>Buildings.Templates.Components.Types.Valve.None
    "Control bus"

  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal y1(
    final realTrue=1,
    final realFalse=0)
    if is_actTwo
    "Two-position signal"
  Modelica.Blocks.Routing.RealPassThrough y if is_actMod
    "Modulating signal"
  Modelica.Blocks.Routing.RealPassThrough y_actual if is_actMod
    "Position feedback"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold y1_actual(t=0.99, h=0.5E-2)
    if is_actTwo
    "Open end switch status"
  Buildings.Controls.OBC.CDL.Reals.LessThreshold y0_actual(t=0.01, h=0.5E-2)
    if is_actTwo
    "Closed end switch status"

  Routing.PassThroughFluid non(
    redeclare final package Medium = Medium)
    if typ==Buildings.Templates.Components.Types.Valve.None
    "No valve"
  Buildings.Fluid.Actuators.Valves.TwoWayEqualPercentage equ(
    redeclare final package Medium=Medium,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final m_flow_nominal=m_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal=dpFixed_nominal,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=init,
    final y_start=y_start,
    final allowFlowReversal=allowFlowReversal,
    final show_T=show_T,
    final from_dp=from_dp,
    final linearized=linearized)
    if is_twoWay
    and chaTwo==Buildings.Templates.Components.Types.ValveCharacteristicTwoWay.EqualPercentage
    "Two-way valve with equal percentage characteristic"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear lin(
    redeclare final package Medium=Medium,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final m_flow_nominal=m_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal=dpFixed_nominal,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=init,
    final y_start=y_start,
    final allowFlowReversal=allowFlowReversal,
    final show_T=show_T,
    final from_dp=from_dp,
    final linearized=linearized)
    if is_twoWay
    and chaTwo==Buildings.Templates.Components.Types.ValveCharacteristicTwoWay.Linear
    "Two-way valve with linear characteristic"
  Buildings.Fluid.Actuators.Valves.TwoWayPressureIndependent ind(
    redeclare final package Medium = Medium,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final m_flow_nominal=m_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal=dpFixed_nominal,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=init,
    final y_start=y_start,
    final allowFlowReversal=allowFlowReversal,
    final show_T=show_T,
    final from_dp=from_dp) if is_twoWay and chaTwo == Buildings.Templates.Components.Types.ValveCharacteristicTwoWay.PressureIndependent
    "Pressure independent two-way valve"
  Buildings.Fluid.Actuators.Valves.TwoWayTable tab(
    redeclare final package Medium=Medium,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final flowCharacteristics=flowCharacteristics,
    final m_flow_nominal=m_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal=dpFixed_nominal,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=init,
    final y_start=y_start,
    final allowFlowReversal=allowFlowReversal,
    final show_T=show_T,
    final from_dp=from_dp,
    final linearized=linearized)
    if is_twoWay
    and chaTwo==Buildings.Templates.Components.Types.ValveCharacteristicTwoWay.Table
    "Pressure independent two-way valve"
  Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear equLin(
    redeclare final package Medium = Medium,
    final fraK=fraK,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final m_flow_nominal=m_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal={dpFixed_nominal,dpFixedByp_nominal},
    final energyDynamics=energyDynamics,
    final tau=tau,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=init,
    final y_start=y_start,
    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,
    final from_dp=from_dp,
    final linearized={linearized,linearized}) if is_thrWay and chaThr ==
    Buildings.Templates.Components.Types.ValveCharacteristicThreeWay.EqualPercentageLinear
    "Three-way valve with equal percentage and linear characteristics"
  Fluid.Actuators.Valves.ThreeWayLinear linLin(
    redeclare final package Medium = Medium,
    final fraK=fraK,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final m_flow_nominal=m_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal={dpFixed_nominal,dpFixedByp_nominal},
    final energyDynamics=energyDynamics,
    final tau=tau,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=init,
    final y_start=y_start,
    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,
    final from_dp=from_dp,
    final linearized={linearized,linearized}) if is_thrWay and chaThr ==
    Buildings.Templates.Components.Types.ValveCharacteristicThreeWay.Linear
    "Three-way valve with linear characteristics"
  Fluid.Actuators.Valves.ThreeWayTable tabTab(
    redeclare final package Medium = Medium,
    final flowCharacteristics1=flowCharacteristics1,
    final flowCharacteristics3=flowCharacteristics3,
    final fraK=fraK,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final m_flow_nominal=m_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal={dpFixed_nominal,dpFixedByp_nominal},
    final energyDynamics=energyDynamics,
    final tau=tau,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=init,
    final y_start=y_start,
    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,
    final from_dp=from_dp,
    final linearized={linearized,linearized}) if is_thrWay and chaThr ==
    Buildings.Templates.Components.Types.ValveCharacteristicThreeWay.Table
    "Three-way valve with table-specified characteristics"
equation
  /* Control point connection - start */
  connect(y1.y, lin.y);
  connect(y.y, lin.y);
  connect(y_actual.u, lin.y_actual);
  connect(y0_actual.u, lin.y_actual);
  connect(y1_actual.u, lin.y_actual);
  connect(y1.y, equ.y);
  connect(y.y, equ.y);
  connect(y_actual.u, equ.y_actual);
  connect(y0_actual.u, equ.y_actual);
  connect(y1_actual.u, equ.y_actual);
  connect(y1.y, tab.y);
  connect(y.y, tab.y);
  connect(y_actual.u, tab.y_actual);
  connect(y0_actual.u, tab.y_actual);
  connect(y1_actual.u, tab.y_actual);
  connect(y1.y, ind.y);
  connect(y.y, ind.y);
  connect(y_actual.u, ind.y_actual);
  connect(y0_actual.u, ind.y_actual);
  connect(y1_actual.u, ind.y_actual);
  connect(y1.y, equLin.y);
  connect(y.y, equLin.y);
  connect(y_actual.u, equLin.y_actual);
  connect(y0_actual.u, equLin.y_actual);
  connect(y1_actual.u, equLin.y_actual);
  connect(y1.y, linLin.y);
  connect(y.y, linLin.y);
  connect(y_actual.u, linLin.y_actual);
  connect(y0_actual.u, linLin.y_actual);
  connect(y1_actual.u, linLin.y_actual);
  connect(y1.y, tabTab.y);
  connect(y.y, tabTab.y);
  connect(y_actual.u, tabTab.y_actual);
  connect(y0_actual.u, tabTab.y_actual);
  connect(y1_actual.u, tabTab.y_actual);
  /* Control point connection - stop */
  connect(port_a, non.port_a)
  connect(non.port_b, port_b)
  connect(port_a, equ.port_a)
  connect(equ.port_b, port_b)
  connect(lin.port_b, port_b)
  connect(port_a, lin.port_a)
  connect(port_a, ind.port_a)
  connect(port_a, tab.port_a)
  connect(ind.port_b, port_b)
  connect(tab.port_b, port_b)
  connect(bus.y1, y1.u)
  connect(bus.y, y.u)
  connect(bus.y_actual, y_actual.y)
  connect(equLin.port_3, portByp_a)
  connect(port_a, equLin.port_1)
  connect(equLin.port_2, port_b)
  connect(bus.y0_actual, y0_actual.y)
  connect(bus.y1_actual, y1_actual.y)
  connect(tabTab.port_2, port_b)
  connect(tabTab.port_3, portByp_a)
  connect(port_a, tabTab.port_1)
  connect(port_a, linLin.port_1)
  connect(linLin.port_3, portByp_a)
  connect(linLin.port_2, port_b)
end Valve;


Compression chiller

within Buildings.Templates.Components.Chillers;
model Compression
  "Compression chiller"
  extends Buildings.Templates.Components.Interfaces.PartialChiller;
  Buildings.Fluid.Chillers.ElectricReformulatedEIR chi(
    redeclare final package Medium1=MediumCon,
    redeclare final package Medium2=MediumChiWat,
    final m1_flow_nominal=mCon_flow_nominal,
    final m2_flow_nominal=mChiWat_flow_nominal,
    final dp1_nominal=if have_dpCon then dpCon_nominal else 0,
    final dp2_nominal=if have_dpChiWat then dpChiWat_nominal else 0,
    final have_switchover=have_switchover,
    final per=dat.perSca,
    final tau1=tau,
    final tau2=tau,
    final energyDynamics=energyDynamics,
    final allowFlowReversal1=allowFlowReversal1,
    final allowFlowReversal2=allowFlowReversal2,
    final show_T=show_T,
    final m1_flow_small=m1_flow_small,
    final m2_flow_small=m2_flow_small)
    "Chiller"
  Controls.StatusEmulator y1_actual
    "Compute chiller status"
  Buildings.Controls.OBC.CDL.Routing.BooleanExtractSignal reqConWat(
    final nin=1,
    final nout=1,
    final extract={1})
    if typ == Buildings.Templates.Components.Types.Chiller.WaterCooled
    "Compute CW request"
  Buildings.Controls.OBC.CDL.Logical.Not off
    "Return true if status is off"
  Buildings.Controls.OBC.CDL.Logical.TrueDelay delOff(
    delayTime=180)
    "Delay off status"
  Buildings.Controls.OBC.CDL.Logical.Not reqFlo
    "Compute flow request"
equation
  connect(port_a1, chi.port_a1)
  connect(chi.port_b1, port_b1)
  connect(port_b2, chi.port_b2)
  connect(chi.port_a2, port_a2)
  connect(bus.y1, chi.on)
  connect(bus.TSupSet, chi.TSet)
  connect(bus.y1Coo, chi.coo)
  connect(bus.y1, y1_actual.y1)
  connect(y1_actual.y1_actual, bus.y1_actual)
  connect(reqConWat.y[1], bus.reqConWat)
  connect(y1_actual.y1_actual, off.u)
  connect(off.y, delOff.u)
  connect(delOff.y, reqFlo.u)
  connect(reqFlo.y, bus.reqChiWat)
  connect(reqFlo.y, reqConWat.u[1])
end Compression;


Chiller models

within Buildings.Templates.Components;
package Chillers
  "Chiller models"
  extends Modelica.Icons.VariantsPackage;
end Chillers;


within Buildings.Templates.Components.Chillers.Validation;
model Compression
  "Validation model for compression chiller component"
  extends Modelica.Icons.Example;
  replaceable package MediumLiq=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "CHW or CW medium";
  replaceable package MediumAir=Buildings.Media.Air
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Air medium";
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  parameter Data.Chiller datChiAirCoo(
    final typ=chiAirCoo.typ,
    final use_datDes=true,
    mChiWat_flow_nominal=datChiAirCoo.cap_nominal / abs(datChiAirCoo.TChiWatSup_nominal -
      Buildings.Templates.Data.Defaults.TChiWatRet) / datChiAirCoo.cpChiWat_default,
    cap_nominal=750E3,
    COP_nominal=Buildings.Templates.Data.Defaults.COPChiAirCoo,
    dpChiWat_nominal=Buildings.Templates.Data.Defaults.dpChiWatChi,
    TChiWatSup_nominal=Buildings.Templates.Data.Defaults.TChiWatSup,
    TConEnt_nominal=Buildings.Templates.Data.Defaults.TOutChi,
    PLR_min=0.15,
    per(
      capFunT={0.0, 0.1, - 0.0023814154, 0.0628316481, - 0.0009644649, -
        0.0011249224},
      EIRFunT={0.0, 0.0071530312, - 0.0004553574, 0.0188175079, 0.0002623276, -
        0.0012881189},
      EIRFunPLR={- 5.497250E-01, 5.035076E-02, - 1.927855E-05, 1.678371E+00, -
        1.535993E+00, - 4.944902E-02, 0.000000E+00, 1.396972E+00, 0.000000E+00, 0.000000E+00},
      PLRMax=1.15,
      etaMotor=1.0))
    "Air-cooled chiller parameters – Parameterization based on design conditions and direct assignment of performance curves"
  parameter Buildings.Templates.Components.Data.Chiller datChiWatCoo(
    final typ=chiWatCoo.typ,
    final use_datDes=false,
    dpChiWat_nominal=Buildings.Templates.Data.Defaults.dpChiWatChi,
    dpCon_nominal=Buildings.Templates.Data.Defaults.dpConWatChi,
    redeclare Buildings.Fluid.Chillers.Data.ElectricReformulatedEIR.ReformEIRChiller_Trane_CVHE_1442kW_6_61COP_VSD per)
    "Water-cooled chiller parameters – Parameterization based on rating conditions specified in the sub-record per"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSupSet(
    k=datChiAirCoo.TChiWatSup_nominal,
    y(final unit="K",
      displayUnit="degC"))
    "CHWST setpoint"
  Buildings.Templates.Components.Chillers.Compression chiAirCoo(
    redeclare final package MediumChiWat=MediumLiq,
    redeclare final package MediumCon=MediumAir,
    final typ=Buildings.Templates.Components.Types.Chiller.AirCooled,
    show_T=true,
    final dat=datChiAirCoo,
    final energyDynamics=energyDynamics)
    "Air-cooled chiller"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1(
    table=[
      0, 0;
      0.5, 1],
    timeScale=1000,
    period=3000)
    "Heat pump Enable signal"
  Fluid.Sensors.TemperatureTwoPort TSup(
    redeclare final package Medium=MediumLiq,
    final m_flow_nominal=datChiAirCoo.mChiWat_flow_nominal)
    "Supply temperature"
  Fluid.Sources.Boundary_pT supChiWat(
    redeclare final package Medium=MediumLiq,
    p=Buildings.Templates.Data.Defaults.pChiWat_rel_nominal + 101325,
    nPorts=2)
    "Boundary condition at distribution system supply"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRet(
    amplitude=(datChiAirCoo.TChiWatRet_nominal - datChiAirCoo.TChiWatSup_nominal) /
      2,
    freqHz=2 / 3000,
    y(final unit="K",
      displayUnit="degC"),
    offset=datChiAirCoo.TChiWatSup_nominal +(datChiAirCoo.TChiWatRet_nominal -
      datChiAirCoo.TChiWatSup_nominal) / 2,
    startTime=0)
    "CHW return temperature value"
  Fluid.Sources.Boundary_pT retChiWat(
    redeclare final package Medium=MediumLiq,
    p=supChiWat.p + chiAirCoo.dpChiWat_nominal,
    use_T_in=true,
    nPorts=1)
    "Boundary conditions of CHW at chiller inlet"
  Fluid.Sensors.TemperatureTwoPort TRet(
    redeclare final package Medium=MediumLiq,
    final m_flow_nominal=datChiAirCoo.mChiWat_flow_nominal)
    "Return temperature"
  Buildings.Templates.Components.Chillers.Compression chiWatCoo(
    redeclare final package MediumChiWat=MediumLiq,
    redeclare final package MediumCon=MediumLiq,
    final typ=Buildings.Templates.Components.Types.Chiller.WaterCooled,
    show_T=true,
    final dat=datChiWatCoo,
    have_dpChiWat=false,
    have_dpCon=false,
    final energyDynamics=energyDynamics)
    "Water-cooled chiller - CHW/CW pressure drops computed externally"
  Fluid.Sensors.TemperatureTwoPort TRet2(
    redeclare final package Medium=MediumLiq,
    final m_flow_nominal=datChiAirCoo.mChiWat_flow_nominal)
    "Return temperature"
  Fluid.Sensors.TemperatureTwoPort TSup2(
    redeclare final package Medium=MediumLiq,
    final m_flow_nominal=datChiAirCoo.mChiWat_flow_nominal)
    "Supply temperature"
  Fluid.Sources.Boundary_pT supConWat(
    redeclare final package Medium=MediumLiq,
    p=retConWat.p + chiWatCoo.dpCon_nominal,
    T=datChiWatCoo.TConEnt_nominal,
    nPorts=1)
    "Boundary conditions of CW at chiller inlet"
  Fluid.Sources.Boundary_pT retConWat(
    redeclare final package Medium=MediumLiq,
    p=Buildings.Templates.Data.Defaults.pChiWat_rel_nominal + 101325,
    nPorts=1)
    "Boundary condition of CW at chiller outlet"
  Fluid.FixedResistances.PressureDrop resChiWat(
    redeclare final package Medium=MediumLiq,
    final m_flow_nominal=datChiWatCoo.mChiWat_flow_nominal,
    final dp_nominal=datChiWatCoo.dpChiWat_nominal)
    "CHW pressure drop computed externally"
  Fluid.FixedResistances.PressureDrop resConWat(
    redeclare final package Medium=MediumLiq,
    final m_flow_nominal=datChiWatCoo.mCon_flow_nominal,
    final dp_nominal=datChiWatCoo.dpCon_nominal)
    "CW pressure drop computed externally"
  Fluid.Sources.Boundary_pT sinAir(
    redeclare final package Medium=MediumAir,
    nPorts=1)
    "Air sink"
  Fluid.Sources.MassFlowSource_T souAir(
    redeclare final package Medium=MediumAir,
    m_flow=datChiAirCoo.mCon_flow_nominal,
    T=datChiAirCoo.TConEnt_nominal,
    nPorts=1)
    "Air source"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRet1(
    amplitude=(datChiWatCoo.TChiWatRet_nominal - datChiWatCoo.TChiWatSup_nominal) /
      2,
    freqHz=2 / 3000,
    y(final unit="K",
      displayUnit="degC"),
    offset=datChiWatCoo.TChiWatSup_nominal +(datChiAirCoo.TChiWatRet_nominal -
      datChiWatCoo.TChiWatSup_nominal) / 2,
    startTime=0)
    "CHW return temperature value"
  Fluid.Sources.Boundary_pT retChiWat1(
    redeclare final package Medium=MediumLiq,
    p=supChiWat.p + chiAirCoo.dpChiWat_nominal,
    use_T_in=true,
    nPorts=1)
    "Boundary conditions of CHW at chiller inlet"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSupSet1(
    k=datChiWatCoo.TChiWatSup_nominal,
    y(final unit="K",
      displayUnit="degC"))
    "CHWST setpoint"
protected
  Interfaces.Bus bus
    "Chiller control bus"
  Interfaces.Bus bus2
    "Chiller control bus"
initial equation
  Modelica.Utilities.Streams.print("Coef at rating conditions = " + String(Buildings.Utilities.Math.Functions.biquadratic(
    a=datChiWatCoo.per.capFunT,
    x1=Modelica.Units.Conversions.to_degC(datChiWatCoo.per.TEvaLvg_nominal),
    x2=Modelica.Units.Conversions.to_degC(datChiWatCoo.per.TConLvg_nominal))));
equation
  connect(TSup.port_b, supChiWat.ports[1])
  connect(y1.y[1], bus.y1)
  connect(bus, chiAirCoo.bus)
  connect(retChiWat.ports[1], TRet.port_a)
  connect(TSup2.port_b, supChiWat.ports[2])
  connect(bus2, chiWatCoo.bus)
  connect(y1.y[1], bus2.y1)
  connect(TRet2.port_b, resChiWat.port_a)
  connect(supConWat.ports[1], resConWat.port_a)
  connect(TRet.port_b, chiAirCoo.port_a2)
  connect(chiAirCoo.port_b2, TSup.port_a)
  connect(chiWatCoo.port_b2, TSup2.port_a)
  connect(resChiWat.port_b, chiWatCoo.port_a2)
  connect(resConWat.port_b, chiWatCoo.port_a1)
  connect(chiWatCoo.port_b1, retConWat.ports[1])
  connect(TChiWatRet.y, retChiWat.T_in)
  connect(TChiWatSupSet.y, bus.TSupSet)
  connect(sinAir.ports[1], chiAirCoo.port_b1)
  connect(souAir.ports[1], chiAirCoo.port_a1)
  connect(TChiWatRet1.y, retChiWat1.T_in)
  connect(retChiWat1.ports[1], TRet2.port_a)
  connect(TChiWatSupSet1.y, bus2.TSupSet)
end Compression;


Package with validation models

within Buildings.Templates.Components.Chillers;
package Validation
  "Package with validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Modulating electric heating coil

within Buildings.Templates.Components.Coils;
model ElectricHeating "Modulating electric heating coil"
  extends Buildings.Templates.Components.Interfaces.PartialCoil(
    final typ=Buildings.Templates.Components.Types.Coil.ElectricHeating,
    final typVal=Buildings.Templates.Components.Types.Valve.None);

  Buildings.Fluid.HeatExchangers.HeaterCooler_u hex(
    redeclare final package Medium = MediumAir,
    final Q_flow_nominal=dat.Q_flow_nominal,
    final m_flow_nominal=dat.mAir_flow_nominal,
    final dp_nominal=dat.dpAir_nominal,
    final energyDynamics=energyDynamics,
    final tau=tau,
    final allowFlowReversal=allowFlowReversalAir,
    final show_T=show_T)
    "Heat exchanger"
equation
  connect(port_a, hex.port_a)
  connect(hex.port_b, port_b)
  connect(bus.y, hex.u)
end ElectricHeating;


within Buildings.Templates.Components.Coils;
model EvaporatorMultiStage
  "Evaporator coil with multi-stage compressor"
  extends Buildings.Templates.Components.Interfaces.PartialCoil(
    final typ=Buildings.Templates.Components.Types.Coil.EvaporatorMultiStage,
    final typVal=Buildings.Templates.Components.Types.Valve.None);

  parameter Boolean have_dryCon = true
    "Set to true for air-cooled condenser, false for evaporative condenser";

  Buildings.Fluid.DXSystems.Cooling.AirSource.MultiStage hex(
    redeclare final package Medium = MediumAir,
    final datCoi=dat.datCoi,
    final dp_nominal=dpAir_nominal,
    final energyDynamics=energyDynamics,
    final tau=tau,
    final allowFlowReversal=allowFlowReversalAir,
    final show_T=show_T)
    "Heat exchanger"

  Modelica.Blocks.Routing.RealPassThrough TWetBul if not have_dryCon
  Modelica.Blocks.Routing.RealPassThrough TDry if have_dryCon
equation
  connect(port_a, hex.port_a)
  connect(hex.port_b, port_b)
  connect(busWea.TWetBul, TWetBul.u)
  connect(busWea.TDryBul, TDry.u)
  connect(TWetBul.y, hex.TOut)
  connect(TDry.y, hex.TOut)
  connect(bus.y, hex.stage)
end EvaporatorMultiStage;


within Buildings.Templates.Components.Coils;
model EvaporatorVariableSpeed
  "Evaporator coil with variable speed compressor"
  extends Buildings.Templates.Components.Interfaces.PartialCoil(
    final typ=Buildings.Templates.Components.Types.Coil.EvaporatorVariableSpeed,
    final typVal=Buildings.Templates.Components.Types.Valve.None);

  parameter Boolean have_dryCon = true
    "Set to true for air-cooled condenser, false for evaporative condenser";

  Buildings.Fluid.DXSystems.Cooling.AirSource.VariableSpeed hex(
    redeclare final package Medium = MediumAir,
    final datCoi=dat.datCoi,
    final minSpeRat=dat.datCoi.minSpeRat,
    final dp_nominal=dpAir_nominal,
    final energyDynamics=energyDynamics,
    final tau=tau,
    final allowFlowReversal=allowFlowReversalAir,
    final show_T=show_T)
    "Heat exchanger"

  Modelica.Blocks.Routing.RealPassThrough TWetBul if not have_dryCon
  Modelica.Blocks.Routing.RealPassThrough TDry if have_dryCon
equation
  connect(port_a, hex.port_a)
  connect(hex.port_b, port_b)
  connect(busWea.TWetBul, TWetBul.u)
  connect(busWea.TDryBul, TDry.u)
  connect(TWetBul.y, hex.TOut)
  connect(TDry.y, hex.TOut)
  connect(bus.y, hex.speRat)
end EvaporatorVariableSpeed;


No coil. This is a direct fluid pass-through model to represent
a configuration with no coil.

within Buildings.Templates.Components.Coils;
model None "No coil"
  extends Buildings.Templates.Components.Interfaces.PartialCoil(
    final typ=Buildings.Templates.Components.Types.Coil.None,
    final typVal=Buildings.Templates.Components.Types.Valve.None);

equation
  connect(port_a, port_b)
end None;


Coil models

within Buildings.Templates.Components;
package Coils "Coil models"
  extends Modelica.Icons.VariantsPackage;
end Coils;


Chilled water coil

within Buildings.Templates.Components.Coils;
model WaterBasedCooling "Chilled water coil"
  extends Buildings.Templates.Components.Interfaces.PartialCoil(
    final typ=Buildings.Templates.Components.Types.Coil.WaterBasedCooling,
    typVal=Buildings.Templates.Components.Types.Valve.TwoWayModulating,
    redeclare final package MediumSou = MediumChiWat);

  replaceable package MediumChiWat=Buildings.Media.Water
    "Source side medium";

  final parameter Modelica.Units.SI.MassFlowRate mWat_flow_nominal=
    dat.mWat_flow_nominal
    "Liquid mass flow rate";
  final parameter Modelica.Units.SI.PressureDifference dpWat_nominal=
    dat.dpWat_nominal
    "Liquid pressure drop across coil";
  final parameter Modelica.Units.SI.PressureDifference dpValve_nominal=
    dat.dpValve_nominal
    "Nominal pressure drop across fully open valve";

  Buildings.Templates.Components.Actuators.Valve val(
    redeclare final package Medium = MediumChiWat,
    final typ=typVal,
    final energyDynamics=energyDynamics,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversalLiq,
    final show_T=show_T,
    final dat=datVal)
    "Valve"

  replaceable Buildings.Fluid.HeatExchangers.WetCoilEffectivenessNTU hex(
    configuration=Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow,
    final use_Q_flow_nominal=true,
    final Q_flow_nominal=Q_flow_nominal,
    final T_a1_nominal=dat.TWatEnt_nominal,
    final T_a2_nominal=dat.TAirEnt_nominal,
    final w_a2_nominal=dat.wAirEnt_nominal,
    final dp1_nominal=if val.typ==Buildings.Templates.Components.Types.Valve.None
      then dpWat_nominal else 0,
    final dp2_nominal=dpAir_nominal)
  constrainedby Buildings.Fluid.Interfaces.PartialFourPortInterface(
    redeclare final package Medium1 = MediumChiWat,
    redeclare final package Medium2 = MediumAir,
    final m1_flow_nominal=mWat_flow_nominal,
    final m2_flow_nominal=mAir_flow_nominal,
    final allowFlowReversal1=allowFlowReversalLiq,
    final allowFlowReversal2=allowFlowReversalAir,
    final show_T=show_T)
    "Heat exchanger"

  Buildings.Fluid.FixedResistances.Junction jun(
    redeclare final package Medium = MediumChiWat,
    final m_flow_nominal=mWat_flow_nominal*{1,-1,-1},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    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 typVal==Buildings.Templates.Components.Types.Valve.ThreeWayModulating
    "Junction"
  Buildings.Templates.Components.Routing.PassThroughFluid pas(
    redeclare final package Medium = MediumChiWat,
    final allowFlowReversal=allowFlowReversalLiq)
    if typVal <> Buildings.Templates.Components.Types.Valve.ThreeWayModulating
    "Direct pass through"
equation
  connect(port_a,hex. port_a2)
  connect(hex.port_b2, port_b)
  connect(val.port_a, hex.port_b1)
  connect(val.port_b, port_bSou)
  connect(val.portByp_a, jun.port_3)
  connect(jun.port_2, hex.port_a1)
  connect(port_aSou, jun.port_1)
  connect(port_aSou, pas.port_a)
  connect(pas.port_b, hex.port_a1)
  connect(val.bus, bus)
end WaterBasedCooling;


Hot water coil

within Buildings.Templates.Components.Coils;
model WaterBasedHeating "Hot water coil"
  extends Buildings.Templates.Components.Interfaces.PartialCoil(
    final typ=Buildings.Templates.Components.Types.Coil.WaterBasedHeating,
    typVal=Buildings.Templates.Components.Types.Valve.TwoWayModulating,
    redeclare final package MediumSou = MediumHeaWat);

  replaceable package MediumHeaWat=Buildings.Media.Water
    "Source side medium";

  final parameter Modelica.Units.SI.MassFlowRate mWat_flow_nominal=
    dat.mWat_flow_nominal
    "Liquid mass flow rate";
  final parameter Modelica.Units.SI.PressureDifference dpWat_nominal=
    dat.dpWat_nominal
    "Liquid pressure drop across coil";
  final parameter Modelica.Units.SI.PressureDifference dpValve_nominal=
    dat.dpValve_nominal
    "Nominal pressure drop across fully open valve";

  Buildings.Templates.Components.Actuators.Valve val(
    final typ=typVal,
    redeclare final package Medium = MediumHeaWat,
    final energyDynamics=energyDynamics,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversalLiq,
    final show_T=show_T,
    final dat=datVal)
    "Valve"

  replaceable Buildings.Fluid.HeatExchangers.DryCoilEffectivenessNTU hex(
    configuration=Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow,
    final use_Q_flow_nominal=true,
    final Q_flow_nominal=Q_flow_nominal,
    final T_a1_nominal=dat.TWatEnt_nominal,
    final T_a2_nominal=dat.TAirEnt_nominal,
    final dp1_nominal=if val.typ==Buildings.Templates.Components.Types.Valve.None
      then dpWat_nominal else 0,
    final dp2_nominal=dpAir_nominal)
  constrainedby Buildings.Fluid.Interfaces.PartialFourPortInterface(
    redeclare final package Medium1 = MediumHeaWat,
    redeclare final package Medium2 = MediumAir,
    final m1_flow_nominal=mWat_flow_nominal,
    final m2_flow_nominal=mAir_flow_nominal,
    final allowFlowReversal1=allowFlowReversalLiq,
    final allowFlowReversal2=allowFlowReversalAir,
    final show_T=show_T)
    "Heat exchanger"

  Buildings.Templates.Components.Routing.PassThroughFluid pas(
    redeclare final package Medium = MediumHeaWat,
    final allowFlowReversal=allowFlowReversalLiq)
    if typVal <> Buildings.Templates.Components.Types.Valve.ThreeWayModulating
    "Direct pass through"

  Buildings.Fluid.FixedResistances.Junction jun(
    redeclare final package Medium=MediumHeaWat,
    final m_flow_nominal=mWat_flow_nominal * {1, -1, -1},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    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 typVal==Buildings.Templates.Components.Types.Valve.ThreeWayModulating
    "Junction"
equation
  connect(port_a,hex. port_a2)
  connect(hex.port_b2, port_b)
  connect(val.port_a, hex.port_b1)
  connect(val.port_b, port_bSou)
  connect(port_aSou, pas.port_a)
  connect(pas.port_b, hex.port_a1)
  connect(jun.port_2, hex.port_a1)
  connect(port_aSou, jun.port_1)
  connect(val.portByp_a, jun.port_3)
  connect(bus, val.bus)
end WaterBasedHeating;


Block that converts command signals for multiple units. This block computes the following variables based on a Boolean array
representing the On/Off command signal for a group of multiple
units, such as parallel fans or pumps.

within Buildings.Templates.Components.Controls;
block MultipleCommands
  "Block that converts command signals for multiple units"

  parameter Integer nUni(final min=1, start=1)
    "Number of units"

  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput y1[nUni]
    "Command signal"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1One
    "On/Off signal: true if at least one unit is commanded On"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput nUniOnBou
    "Number of units that are commanded On, with lower bound of 1"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput nUniOn
    "Number of units that are commanded On"

  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea[nUni]
    "Convert to real"
  Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum(nin=nUni)
    "Total"
  Buildings.Controls.OBC.CDL.Reals.Max max1
    "Maximum value"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(final k=1)
    "Constant one"

  Buildings.Controls.OBC.CDL.Logical.MultiOr mulOr(nin=nUni)
    "Returns true if at least one unit is commanded on"
equation
  connect(booToRea.y, mulSum.u)
  connect(max1.y, nUniOnBou)
  connect(mulSum.y, nUniOn)
  connect(one.y, max1.u2)
  connect(mulSum.y, max1.u1)
  connect(y1, booToRea.u)
  connect(y1, mulOr.u)
  connect(y1One, mulOr.y)
end MultipleCommands;


Control blocks

within Buildings.Templates.Components;
package Controls "Control blocks"
  extends Modelica.Icons.VariantsPackage;
end Controls;


Block that emulates the status of an equipment. This block emulates the status of an equipment, i.e.,
the current on/off state as reported by the hardware itself.

within Buildings.Templates.Components.Controls;
block StatusEmulator
  "Block that emulates the status of an equipment"
  parameter Real delayTime(
    final quantity="Time",
    final unit="s")=2
    "Delay time"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput y1
    "Equipment run command"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanOutput y1_actual
    "Equipment status"
  inner Modelica.StateGraph.StateGraphRoot stateGraphRoot
  Modelica.StateGraph.InitialStepWithSignal off(nOut=1, nIn=1)
    "Off status (initial state)"
  Modelica.StateGraph.TransitionWithSignal offToOn(final enableTimer=delayTime
         > 0, final waitTime=delayTime) "Transition from off to on status"
  Modelica.StateGraph.StepWithSignal on(nIn=1, nOut=1) "On status"
  Modelica.StateGraph.TransitionWithSignal onToOff(final enableTimer=delayTime
         > 0, final waitTime=delayTime) "Transition from on to off status"
  Buildings.Controls.OBC.CDL.Logical.Not notY1
    "Return true if equipment commanded off"
equation
  connect(y1, offToOn.condition)
  connect(off.outPort[1], offToOn.inPort)
  connect(on.active, y1_actual)
  connect(notY1.y, onToOff.condition)
  connect(on.outPort[1], onToOff.inPort)
  connect(offToOn.outPort, on.inPort[1])
  connect(onToOff.outPort, off.inPort[1])
  connect(y1, notY1.u)
end StatusEmulator;


Validation model for converter of multiple commands. This model validates

Buildings.Templates.Components.Controls.MultipleCommands.

within Buildings.Templates.Components.Controls.Validation;
model MultipleCommands "Validation model for converter of multiple commands"
  extends Modelica.Icons.Example;
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse y1[3](
    width={0.5,0.6,0.4},
    each period=600,
    shift={100,200,300})
                       "Enable command"
  Buildings.Templates.Components.Controls.MultipleCommands conCom(nUni=3)
    "Converter of multiple commands"
equation
  connect(y1.y, conCom.y1)
end MultipleCommands;


Package with validation models

within Buildings.Templates.Components.Controls;
package Validation "Package with validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Validation model for status emulator. This model validates

Buildings.Templates.Components.Controls.StatusEmulator.

within Buildings.Templates.Components.Controls.Validation;
model StatusEmulator
  "Validation model for status emulator"
  extends Modelica.Icons.Example;
  Buildings.Controls.OBC.CDL.Logical.Sources.Pulse y1(
    period=10)
    "Enable command"
  Buildings.Templates.Components.Controls.StatusEmulator sta
    "Generate status"
equation
  connect(y1.y, sta.y1)
end StatusEmulator;


Record for coil model. This record provides the set of sizing parameters for
the classes within

Buildings.Templates.Components.Coils.

within Buildings.Templates.Components.Data;
record Coil "Record for coil model"
  extends Modelica.Icons.Record;

  parameter Buildings.Templates.Components.Types.Coil typ
    "Equipment type"
  parameter Buildings.Templates.Components.Types.Valve typVal
    "Type of valve"
  parameter Boolean have_sou
    "Set to true for fluid ports on the source side"

  /*
For evaporator coils this is also provided by the performance data record.
The coil model shall generate a warning in case the design value exceeds
the maximum value from the performance data record.
*/
  parameter Modelica.Units.SI.MassFlowRate mAir_flow_nominal(
    final min=0,
    start=if typ==Buildings.Templates.Components.Types.Coil.EvaporatorMultiStage or
      typ==Buildings.Templates.Components.Types.Coil.EvaporatorVariableSpeed then
      datCoi.sta[datCoi.nSta].nomVal.m_flow_nominal
    else 1)
    "Air mass flow rate"
  parameter Modelica.Units.SI.PressureDifference dpAir_nominal(
    final min=0,
    displayUnit="Pa",
    start=if typ==Buildings.Templates.Components.Types.Coil.None then 0 else
    100)
    "Air pressure drop"
  parameter Modelica.Units.SI.MassFlowRate mWat_flow_nominal(
    final min=0,
    start=if typ==Buildings.Templates.Components.Types.Coil.WaterBasedHeating then
      Q_flow_nominal / 4186 / 10 elseif
      typ==Buildings.Templates.Components.Types.Coil.WaterBasedCooling then
      -Q_flow_nominal / 4186 / 5 else
      0)
    "Liquid mass flow rate"
  parameter Modelica.Units.SI.PressureDifference dpWat_nominal(
    final min=0,
    displayUnit="Pa",
    start=if typ==Buildings.Templates.Components.Types.Coil.WaterBasedHeating then
    0.5e4 elseif typ==Buildings.Templates.Components.Types.Coil.WaterBasedCooling then
    3e4 else
    0)
    "Liquid pressure drop across coil"
  parameter Modelica.Units.SI.PressureDifference dpValve_nominal(
    final min=0,
    displayUnit="Pa",
    start=if typVal==Buildings.Templates.Components.Types.Valve.None then 0
    else dpWat_nominal / 2)
    "Liquid pressure drop across fully open valve"
  parameter Modelica.Units.SI.HeatFlowRate cap_nominal(
    start=if typ==Buildings.Templates.Components.Types.Coil.None then 0
    elseif typ==Buildings.Templates.Components.Types.Coil.EvaporatorMultiStage or
      typ==Buildings.Templates.Components.Types.Coil.EvaporatorVariableSpeed then
      datCoi.sta[datCoi.nSta].nomVal.Q_flow_nominal
    elseif typ==Buildings.Templates.Components.Types.Coil.WaterBasedCooling then -1E4
    else 1E4)
    "Coil capacity"
  /*
For evaporator coils this is also provided by the performance data record.
The coil model shall generate a warning in case the design value exceeds
the maximum value from the performance data record.
*/
  final parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=
    if typ==Buildings.Templates.Components.Types.Coil.WaterBasedHeating or
       typ==Buildings.Templates.Components.Types.Coil.ElectricHeating then abs(cap_nominal)
    else -1 * abs(cap_nominal)
    "Nominal heat flow rate"
  parameter Modelica.Units.SI.Temperature TWatEnt_nominal(
    final min=273.15,
    displayUnit="degC",
    start=if typ==Buildings.Templates.Components.Types.Coil.WaterBasedHeating then 50+273.15
    elseif typ==Buildings.Templates.Components.Types.Coil.WaterBasedCooling then 7+273.15
    else 273.15)
    "Nominal entering liquid temperature"
  parameter Modelica.Units.SI.Temperature TAirEnt_nominal(
    final min=243.15,
    displayUnit="degC",
    start=if typ==Buildings.Templates.Components.Types.Coil.WaterBasedCooling then 30+273.15
    else 273.15)
    "Nominal entering air temperature"
  parameter Modelica.Units.SI.MassFraction wAirEnt_nominal(
    final min=0,
    start=0.01)
    "Nominal entering air humidity ratio"
  replaceable parameter
    Buildings.Fluid.DXSystems.Cooling.AirSource.Data.SingleSpeed.Carrier_Centurion_50PG06 datCoi
    constrainedby
    Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.DXCoil
    "Performance data record of evaporator coil"
end Coil;


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


Fan array - Variable speed

within Buildings.Templates.Components.Fans;
model ArrayVariable "Fan array - Variable speed"
  extends Buildings.Templates.Components.Interfaces.PartialFan(
    final typ=Buildings.Templates.Components.Types.Fan.ArrayVariable);

  Buildings.Fluid.Movers.SpeedControlled_y fan(
    redeclare final package Medium = Medium,
    final inputType=Buildings.Fluid.Types.InputType.Continuous,
    final per=dat.per,
    final energyDynamics=energyDynamics,
    final tau=tau,
    use_riseTime=energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal) "Fan array"

  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal sigSta
    "Start/stop signal"
  Buildings.Controls.OBC.CDL.Reals.Multiply sigCon "Resulting control signal"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold evaSta(
    t=1E-2,
    h=0.5E-2)
    "Evaluate fan status"
  Fluid.BaseClasses.MassFlowRateMultiplier mulInl(
    redeclare final package Medium = Medium,
    final use_input=true)
    "Flow rate multiplier"
  Fluid.BaseClasses.MassFlowRateMultiplier mulOut(
    redeclare final package Medium = Medium,
    final use_input=true)
    "Flow rate multiplier"
  Buildings.Templates.Components.Controls.MultipleCommands conCom(final nUni=nFan)
    "Convert command signal"
  Buildings.Controls.OBC.CDL.Reals.Multiply pow "Compute input power"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator rep(final nout=
        nFan) "Replicate"
equation
  connect(sigSta.y, sigCon.u2)
  connect(fan.y_actual, evaSta.u)
  connect(bus.y, sigCon.u1)
  connect(V_flow.port_a, mulOut.port_b)
  connect(port_a, mulInl.port_a)
  connect(mulInl.port_b, fan.port_a)
  connect(fan.port_b, mulOut.port_a)
  connect(conCom.y1One, sigSta.u)
  connect(conCom.nUniOnBou, mulOut.u)
  connect(mulInl.u, mulOut.uInv)
  connect(sigCon.y, fan.y)
  connect(conCom.nUniOn, pow.u1)
  connect(fan.P, pow.u2)
  connect(rep.y, conCom.y1)
  connect(bus.y1, rep.u)
  connect(evaSta.y, bus.y1_actual)
end ArrayVariable;


No fan. This is a direct fluid pass-through model to represent
a configuration with no fan.

within Buildings.Templates.Components.Fans;
model None "No fan"
  extends Buildings.Templates.Components.Interfaces.PartialFan(
    final nFan=0,
    final typ=Buildings.Templates.Components.Types.Fan.None);

equation
  connect(port_a, V_flow.port_a)
end None;


Fan models

within Buildings.Templates.Components;
package Fans "Fan models"
  extends Modelica.Icons.VariantsPackage;
end Fans;


Single fan - Constant speed

within Buildings.Templates.Components.Fans;
model SingleConstant "Single fan - Constant speed"
  extends Buildings.Templates.Components.Interfaces.PartialFan(
    final nFan=1,
    final typ=Buildings.Templates.Components.Types.Fan.SingleConstant);

  Buildings.Fluid.Movers.SpeedControlled_y fan(
    redeclare final package Medium = Medium,
    final inputType=Buildings.Fluid.Types.InputType.Continuous,
    final per=dat.per,
    final energyDynamics=energyDynamics,
    final tau=tau,
    use_riseTime=energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal) "Fan"

  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal sigSta
    "Start/stop signal"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold evaSta(
    t=1E-2,
    h=0.5E-2)
    "Evaluate fan status"
equation
  connect(sigSta.y, fan.y)
  connect(port_a, fan.port_a)
  connect(fan.y_actual, evaSta.u)
  connect(bus.y1, sigSta.u)
  connect(evaSta.y, bus.y1_actual)
  connect(fan.port_b, V_flow.port_a)
end SingleConstant;


Single fan - Variable speed

within Buildings.Templates.Components.Fans;
model SingleVariable "Single fan - Variable speed"
  extends Buildings.Templates.Components.Interfaces.PartialFan(
    final nFan=1,
    final typ=Buildings.Templates.Components.Types.Fan.SingleVariable);

  Buildings.Fluid.Movers.SpeedControlled_y fan(
    redeclare final package Medium = Medium,
    final inputType=Buildings.Fluid.Types.InputType.Continuous,
    final per=dat.per,
    final energyDynamics=energyDynamics,
    final tau=tau,
    use_riseTime=energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal) "Fan"

  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal sigSta
    "Start/stop signal"

  Buildings.Controls.OBC.CDL.Reals.Multiply sigCon
    "Resulting control signal"

  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold evaSta(
    t=1E-2,
    h=0.5E-2)
    "Evaluate fan status"
equation
  connect(port_a, fan.port_a)
  connect(fan.y_actual, evaSta.u)
  connect(bus.y1, sigSta.u)
  connect(evaSta.y, bus.y1_actual)
  connect(sigCon.y, fan.y)
  connect(bus.y, sigCon.u1)
  connect(sigSta.y, sigCon.u2)
  connect(fan.port_b, V_flow.port_a)
end SingleVariable;


within Buildings.Templates.Components.HeatPumps;
model AirToWater
  "Air-to-water heat pump - Equation fit model"
  extends Buildings.Templates.Components.Interfaces.PartialHeatPumpEquationFit(
    redeclare final package MediumSou=MediumAir,
    final typ=Buildings.Templates.Components.Types.HeatPump.AirToWater,
    final allowFlowReversalSou=false);
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter mAir_flow(
    final k=mSouHea_flow_nominal)
    "Air mass flow rate"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal y1Rea
    "Convert on/off command into real"
  Fluid.Movers.BaseClasses.IdealSource floSou(
    redeclare final package Medium=MediumAir,
    final m_flow_small=1E-4 * mSouHea_flow_nominal,
    final allowFlowReversal=allowFlowReversalSou,
    final control_m_flow=true,
    final control_dp=false)
    "Air flow source"
equation
  connect(y1Rea.y, mAir_flow.u)
  connect(floSou.port_b, TSouEnt.port_a)
  connect(port_aSou, floSou.port_a)
  connect(mAir_flow.y, floSou.m_flow_in)
  connect(bus.y1, y1Rea.u)
end AirToWater;


Heat pump models

within Buildings.Templates.Components;
package HeatPumps "Heat pump models"
  extends Modelica.Icons.VariantsPackage;
end HeatPumps;


Water-to-water heat pump - Equation fit model. This is a model for a water-to-water heat pump where the capacity
and input power are computed based on the equation fit method.
The model can be configured with the parameter is_rev
to represent either a non-reversible heat pump (heating only) or a
reversible heat pump.
This model uses

Buildings.Fluid.HeatPumps.EquationFitReversible,
which the user may refer to for the modeling assumptions.

within Buildings.Templates.Components.HeatPumps;
model WaterToWater
  "Water-to-water heat pump - Equation fit model"
  extends Buildings.Templates.Components.Interfaces.PartialHeatPumpEquationFit(
    final typ=Buildings.Templates.Components.Types.HeatPump.WaterToWater);
equation
  connect(port_aSou, TSouEnt.port_a)
end WaterToWater;


within Buildings.Templates.Components.HeatPumps.Validation;
model HeatPumpEquationFit
  "Validation model for heat pump component with equation fit model"
  extends Modelica.Icons.Example;
  replaceable package Medium=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "HW or CHW medium";
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  parameter Buildings.Templates.Components.Data.HeatPump datHpAwNrv(
    final cpHeaWat_default=hpAwNrv.cpHeaWat_default,
    final cpSou_default=hpAwNrv.cpSou_default,
    final typ=hpAwNrv.typ,
    final is_rev=hpAwNrv.is_rev,
    final typMod=hpAwNrv.typMod,
    mHeaWat_flow_nominal=datHpAw.capHea_nominal/abs(datHpAw.THeaWatSup_nominal -
        Buildings.Templates.Data.Defaults.THeaWatRetMed)/Buildings.Utilities.Psychrometrics.Constants.cpWatLiq,
    dpHeaWat_nominal=Buildings.Templates.Data.Defaults.dpHeaWatHp,
    capHea_nominal=500E3,
    THeaWatSup_nominal=Buildings.Templates.Data.Defaults.THeaWatSupMed,
    TSouHea_nominal=Buildings.Templates.Data.Defaults.TOutHpHeaLow,
    perFit(hea(
        P=datHpAwNrv.capHea_nominal/Buildings.Templates.Data.Defaults.COPHpAwHea,
        coeQ={-4.2670305442,-0.7381077035,6.0049480456,0,0},
        coeP={-4.9107455513,5.3665308366,0.5447612754,0,0},
        TRefLoa=Buildings.Templates.Data.Defaults.THeaWatRetMed,
        TRefSou=Buildings.Templates.Data.Defaults.TOutHpHeaLow)))
    "Non-reversible AWHP parameters"

  parameter Buildings.Templates.Components.Data.HeatPump datHpAw(
    final cpHeaWat_default=hpAw.cpHeaWat_default,
    final cpSou_default=hpAw.cpSou_default,
    final typ=hpAw.typ,
    final is_rev=hpAw.is_rev,
    final typMod=hpAw.typMod,
    mHeaWat_flow_nominal=datHpAw.capHea_nominal/abs(datHpAw.THeaWatSup_nominal -
        Buildings.Templates.Data.Defaults.THeaWatRetMed)/Buildings.Utilities.Psychrometrics.Constants.cpWatLiq,
    dpHeaWat_nominal=Buildings.Templates.Data.Defaults.dpHeaWatHp,
    capHea_nominal=500E3,
    THeaWatSup_nominal=Buildings.Templates.Data.Defaults.THeaWatSupMed,
    mChiWat_flow_nominal=datHpAw.capCoo_nominal/abs(datHpAw.TChiWatSup_nominal -
        Buildings.Templates.Data.Defaults.TChiWatRet)/Buildings.Utilities.Psychrometrics.Constants.cpWatLiq,
    capCoo_nominal=500E3,
    TChiWatSup_nominal=Buildings.Templates.Data.Defaults.TChiWatSup,
    TSouCoo_nominal=Buildings.Templates.Data.Defaults.TOutHpCoo,
    TSouHea_nominal=Buildings.Templates.Data.Defaults.TOutHpHeaLow,
    perFit(hea(
        P=datHpAw.capHea_nominal/Buildings.Templates.Data.Defaults.COPHpAwHea,
        coeQ={-4.2670305442,-0.7381077035,6.0049480456,0,0},
        coeP={-4.9107455513,5.3665308366,0.5447612754,0,0},
        TRefLoa=Buildings.Templates.Data.Defaults.THeaWatRetMed,
        TRefSou=Buildings.Templates.Data.Defaults.TOutHpHeaLow), coo(
        P=datHpAw.capCoo_nominal/Buildings.Templates.Data.Defaults.COPHpAwCoo,
        coeQ={-2.2545246871,6.9089257665,-3.6548225094,0,0},
        coeP={-5.8086010402,1.6894933858,5.1167787436,0,0},
        TRefLoa=Buildings.Templates.Data.Defaults.TChiWatRet,
        TRefSou=Buildings.Templates.Data.Defaults.TOutHpCoo)))
    "Reversible AWHP parameters"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TChiWatSupSet(k=datHpAw.TChiWatSup_nominal,
      y(final unit="K", displayUnit="degC")) "CHWST setpoint"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSupSet(k=datHpAw.THeaWatSup_nominal,
      y(final unit="K", displayUnit="degC")) "HW supply temperature setpoint"
  AirToWater hpAw(
    is_rev=true,
    show_T=true,
    redeclare final package MediumHeaWat = Medium,
    final dat=datHpAw,
    final energyDynamics=energyDynamics) "Reversible AWHP"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin THeaWatRet(
    amplitude=datHpAw.THeaWatSup_nominal - datHpAw.THeaWatRet_nominal,
    freqHz=3/3000,
    y(final unit="K", displayUnit="degC"),
    offset=datHpAw.THeaWatRet_nominal,
    startTime=0) "HW return temperature value"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1(
    table=[
      0, 0;
      0.5, 1],
    timeScale=1000,
    period=3000)
    "Heat pump Enable signal"
  Fluid.Sensors.TemperatureTwoPort TSup(redeclare final package Medium = Medium,
      final m_flow_nominal=datHpAw.mChiWat_flow_nominal) "Supply temperature"
  Buildings.Controls.OBC.CDL.Logical.Sources.TimeTable y1Hea(
    table=[
      0, 0;
      2, 1],
    timeScale=1000,
    period=3000)
    "Heat pump heating mode signal"
  Buildings.Controls.OBC.CDL.Reals.Switch TSetAct(
    y(final unit="K",
      displayUnit="degC"))
    "Active supply temperature setpoint"
  Fluid.Sources.Boundary_pT sup(
    redeclare final package Medium=Medium,
    p=Buildings.Templates.Data.Defaults.pHeaWat_rel_nominal + 101325,
    nPorts=3)
    "Boundary condition at distribution system supply"
  Buildings.Controls.OBC.CDL.Reals.Sources.Sin TChiWatRet(
    amplitude=datHpAw.TChiWatRet_nominal - datHpAw.TChiWatSup_nominal,
    freqHz=3/3000,
    y(final unit="K", displayUnit="degC"),
    offset=datHpAw.TChiWatRet_nominal,
    startTime=0) "CHW return temperature value"
  Fluid.Sources.Boundary_pT inlHp(
    redeclare final package Medium = Medium,
    use_p_in=true,
    use_T_in=true,
    nPorts=3) "Boundary conditions of CHW/HW at HP inlet"
  Buildings.Controls.OBC.CDL.Reals.Switch TRetAct
    "Active return temperature"
  Buildings.Controls.OBC.CDL.Reals.Switch pInl_rel
    "Active inlet gaupe pressure"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant pHeaWatInl(
    k=sup.p + hpAw.dpHeaWat_nominal)
    "HW inlet pressure"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant pChiWatInl(
    k=sup.p + hpAw.dpChiWat_nominal)
    "CHW inlet pressure"
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    filNam=Modelica.Utilities.Files.loadResource(
      "modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
  Fluid.Sensors.TemperatureTwoPort TRet(redeclare final package Medium = Medium,
      final m_flow_nominal=datHpAw.mChiWat_flow_nominal) "Return temperature"
  AirToWater hpAwNrv(
    is_rev=false,
    redeclare final package MediumHeaWat = Medium,
    final energyDynamics=energyDynamics,
    final dat=datHpAwNrv) "Non reversible AWHP"
  Fluid.Sensors.TemperatureTwoPort TRet1(redeclare final package Medium =
        Medium, final m_flow_nominal=datHpAw.mChiWat_flow_nominal)
    "Return temperature"
  Fluid.Sensors.TemperatureTwoPort TSup1(redeclare final package Medium =
        Medium, final m_flow_nominal=datHpAw.mChiWat_flow_nominal)
    "Supply temperature"
  WaterToWater hpWw(
    is_rev=true,
    show_T=true,
    redeclare final package MediumHeaWat = Medium,
    final dat=datHpWw,
    final energyDynamics=energyDynamics,
    have_dpChiHeaWat=false,
    have_dpSou=false)
    "Reversible WWHP - CHW/HW and source fluid pressure drops computed externally"
  parameter Data.HeatPump datHpWw(
    final cpHeaWat_default=hpWw.cpHeaWat_default,
    final cpSou_default=hpWw.cpSou_default,
    final typ=hpWw.typ,
    final is_rev=hpWw.is_rev,
    final typMod=hpWw.typMod,
    mHeaWat_flow_nominal=datHpAw.capHea_nominal/abs(datHpAw.THeaWatSup_nominal -
        Buildings.Templates.Data.Defaults.THeaWatRetMed)/Buildings.Utilities.Psychrometrics.Constants.cpWatLiq,
    dpHeaWat_nominal=Buildings.Templates.Data.Defaults.dpHeaWatHp,
    capHea_nominal=500E3,
    THeaWatSup_nominal=Buildings.Templates.Data.Defaults.THeaWatSupMed,
    mChiWat_flow_nominal=datHpAw.capCoo_nominal/abs(datHpAw.TChiWatSup_nominal -
        Buildings.Templates.Data.Defaults.TChiWatRet)/Buildings.Utilities.Psychrometrics.Constants.cpWatLiq,
    capCoo_nominal=500E3,
    TChiWatSup_nominal=Buildings.Templates.Data.Defaults.TChiWatSup,
    TSouCoo_nominal=Buildings.Templates.Data.Defaults.TSouHpCoo,
    TSouHea_nominal=Buildings.Templates.Data.Defaults.TSouHpHea,
    dpSouWwHea_nominal=Buildings.Templates.Data.Defaults.dpChiWatChi,
    mSouWwCoo_flow_nominal=datHpWw.mSouWwHea_flow_nominal,
    mSouWwHea_flow_nominal=datHpWw.mHeaWat_flow_nominal,
    perFit(hea(
        P=datHpAw.capHea_nominal/Buildings.Templates.Data.Defaults.COPHpWwHea,
        coeQ={-4.2670305442,-0.7381077035,6.0049480456,0,0},
        coeP={-4.9107455513,5.3665308366,0.5447612754,0,0},
        TRefLoa=Buildings.Templates.Data.Defaults.THeaWatRetMed,
        TRefSou=Buildings.Templates.Data.Defaults.TSouHpHea), coo(
        P=datHpAw.capCoo_nominal/Buildings.Templates.Data.Defaults.COPHpWwCoo,
        coeQ={-2.2545246871,6.9089257665,-3.6548225094,0,0},
        coeP={-5.8086010402,1.6894933858,5.1167787436,0,0},
        TRefLoa=Buildings.Templates.Data.Defaults.TChiWatRet,
        TRefSou=Buildings.Templates.Data.Defaults.TSouHpCoo)))
    "Reversible WWHP parameters"

  Fluid.Sensors.TemperatureTwoPort TRet2(redeclare final package Medium =
        Medium, final m_flow_nominal=datHpAw.mChiWat_flow_nominal)
    "Return temperature"
  Fluid.Sensors.TemperatureTwoPort TSup2(redeclare final package Medium =
        Medium, final m_flow_nominal=datHpAw.mChiWat_flow_nominal)
    "Supply temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TSouHea(
    y(final unit="K", displayUnit="degC"),
    height=4,
    duration=500,
    offset=datHpWw.TSouHea_nominal,
    startTime=2400) "Source fluid supply temperature value"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TSouCoo(
    y(final unit="K", displayUnit="degC"),
    height=-4,
    duration=500,
    offset=datHpWw.TSouCoo_nominal,
    startTime=1400) "Source fluid supply temperature value"
  Buildings.Controls.OBC.CDL.Reals.Switch TSouAct
    "Active source fluid supply temperature"
  Buildings.Controls.OBC.CDL.Reals.Switch pInl_rel1
    "Active inlet gaupe pressure"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant pSouInlHea(k=retSou.p +
        hpWw.dpSouHea_nominal) "Source fluid inlet pressure"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant pSouInlCoo(k=retSou.p +
        hpWw.dpSouCoo_nominal) "Source fluid inlet pressure"
  Fluid.Sources.Boundary_pT inlHpSou(
    redeclare final package Medium = Medium,
    use_p_in=true,
    use_T_in=true,
    nPorts=1) "Boundary conditions or source side fluid at HP inlet"
  Fluid.Sources.Boundary_pT retSou(
    redeclare final package Medium=Medium,
    p=Buildings.Templates.Data.Defaults.pHeaWat_rel_nominal + 101325,
    nPorts=1)
    "Boundary condition at source system return"
  Fluid.FixedResistances.PressureDrop res(
    redeclare final package Medium = Medium,
    final m_flow_nominal=datHpWw.mHeaWat_flow_nominal,
    final dp_nominal=datHpWw.dpHeaWat_nominal)
    "CHW/HW pressure drop computed externally"
  Fluid.FixedResistances.PressureDrop resSou(
    redeclare final package Medium = Medium,
    final m_flow_nominal=datHpWw.mSouWwHea_flow_nominal,
    final dp_nominal=datHpWw.dpSouWwHea_nominal)
    "Source fluid pressure drop computed externally"
protected
  Interfaces.Bus bus "HP control bus"
protected
  Interfaces.Bus bus1 "HP control bus"
protected
  Interfaces.Bus bus2 "HP control bus"
equation
  connect(y1Hea.y[1], TSetAct.u2)
  connect(TChiWatSupSet.y, TSetAct.u3)
  connect(THeaWatSupSet.y, TSetAct.u1)
  connect(TSup.port_b, sup.ports[1])
  connect(THeaWatRet.y, TRetAct.u1)
  connect(y1Hea.y[1], TRetAct.u2)
  connect(TChiWatRet.y, TRetAct.u3)
  connect(hpAw.port_b, TSup.port_a)
  connect(TRetAct.y, inlHp.T_in)
  connect(y1Hea.y[1], bus.y1Hea)
  connect(y1.y[1], bus.y1)
  connect(TSetAct.y, bus.TSet)
  connect(pInl_rel.y, inlHp.p_in)
  connect(pHeaWatInl.y, pInl_rel.u1)
  connect(pChiWatInl.y, pInl_rel.u3)
  connect(y1Hea.y[1], pInl_rel.u2)
  connect(bus, hpAw.bus)
  connect(weaDat.weaBus, hpAw.busWea)
  connect(inlHp.ports[1], TRet.port_a)
  connect(TRet.port_b, hpAw.port_a)
  connect(bus1, hpAwNrv.bus)
  connect(y1.y[1], bus1.y1)
  connect(hpAwNrv.port_b, TSup1.port_a)
  connect(TRet1.port_b, hpAwNrv.port_a)
  connect(TSup1.port_b, sup.ports[2])
  connect(inlHp.ports[2], TRet1.port_a)
  connect(weaDat.weaBus, hpAwNrv.busWea)
  connect(THeaWatSupSet.y, bus1.TSet)
  connect(hpWw.port_b, TSup2.port_a)
  connect(TSup2.port_b, sup.ports[3])
  connect(inlHp.ports[3], TRet2.port_a)
  connect(bus2, hpWw.bus)
  connect(TSouHea.y, TSouAct.u1)
  connect(y1Hea.y[1], TSouAct.u2)
  connect(TSouCoo.y, TSouAct.u3)
  connect(pSouInlHea.y, pInl_rel1.u1)
  connect(pSouInlCoo.y, pInl_rel1.u3)
  connect(y1Hea.y[1], pInl_rel1.u2)
  connect(retSou.ports[1], hpWw.port_bSou)
  connect(TSouAct.y, inlHpSou.T_in)
  connect(pInl_rel1.y, inlHpSou.p_in)
  connect(TSetAct.y, bus2.TSet)
  connect(y1.y[1], bus2.y1)
  connect(y1Hea.y[1], bus2.y1Hea)
  connect(TRet2.port_b, res.port_a)
  connect(res.port_b, hpWw.port_a)
  connect(hpWw.port_aSou, resSou.port_b)
  connect(inlHpSou.ports[1], resSou.port_a)
end HeatPumpEquationFit;


Package with validation models

within Buildings.Templates.Components.HeatPumps;
package Validation "Package with validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Interface classes

within Buildings.Templates.Components;
package Interfaces "Interface classes"
  extends Modelica.Icons.InterfacesPackage;
end Interfaces;


Interface class for chiller models

within Buildings.Templates.Components.Interfaces;
partial model PartialChiller
  "Interface class for chiller models"
  extends Buildings.Fluid.Interfaces.PartialFourPortInterface(
    redeclare final package Medium1=MediumCon,
    redeclare final package Medium2=MediumChiWat,
    final m1_flow_nominal=mCon_flow_nominal,
    final m2_flow_nominal=mChiWat_flow_nominal);
  replaceable package MediumChiWat=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "CHW medium"
  replaceable package MediumCon=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Medium model for condenser cooling fluid"
  parameter Buildings.Templates.Components.Types.Chiller typ
    "Type of chiller"
  parameter Boolean have_switchover=false
    "Set to true for heat recovery chiller with built-in switchover"
  parameter Buildings.Templates.Components.Data.Chiller dat(
    typ=typ,
    cpChiWat_default=cpChiWat_default,
    cpCon_default=cpCon_default)
    "Design and operating parameters"
  final parameter Modelica.Units.SI.MassFlowRate mChiWat_flow_nominal=dat.mChiWat_flow_nominal
    "CHW mass flow rate";
  final parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal=dat.mCon_flow_nominal
    "Condenser cooling fluid mass flow rate";
  final parameter Modelica.Units.SI.HeatFlowRate cap_nominal=dat.cap_nominal
    "Cooling capacity";
  final parameter Modelica.Units.SI.PressureDifference dpChiWat_nominal=dat.dpChiWat_nominal
    "CHW pressure drop";
  final parameter Modelica.Units.SI.PressureDifference dpCon_nominal=dat.dpCon_nominal
    "Condenser cooling fluid pressure drop";
  final parameter Modelica.Units.SI.Temperature TChiWatSup_nominal=dat.TChiWatSup_nominal
    "CHW supply temperature";
  final parameter Modelica.Units.SI.Temperature TChiWatRet_nominal=dat.TChiWatRet_nominal
    "CHW return temperature";
  final parameter Modelica.Units.SI.Temperature TConEnt_nominal=dat.TConEnt_nominal
    "Condenser entering fluid temperature";
  final parameter Modelica.Units.SI.Temperature TConLvg_nominal=dat.TConLvg_nominal
    "Condenser leaving fluid temperature";
  parameter Boolean have_dpChiWat=true
    "Set to true for CHW pressure drop computed by this model, false for external computation"
  parameter Boolean have_dpCon=true
    "Set to true for condenser cooling fluid pressure drop computed by this model, false for external computation"
  parameter Modelica.Units.SI.Time tau=30
    "Time constant at 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"
  final parameter MediumChiWat.SpecificHeatCapacity cpChiWat_default=
    MediumChiWat.specificHeatCapacityCp(staChiWat_default)
    "CHW default specific heat capacity";
  final parameter MediumChiWat.ThermodynamicState staChiWat_default=MediumChiWat.setState_pTX(
    T=TChiWatSup_nominal,
    p=MediumChiWat.p_default,
    X=MediumChiWat.X_default)
    "CHW default state";
  final parameter MediumCon.SpecificHeatCapacity cpCon_default=MediumCon.specificHeatCapacityCp(staCon_default)
    "Condenser cooling fluid default specific heat capacity";
  final parameter MediumCon.ThermodynamicState staCon_default=MediumCon.setState_pTX(
    T=TConEnt_nominal,
    p=MediumCon.p_default,
    X=MediumCon.X_default)
    "Condenser cooling fluid default state";
  Buildings.Templates.Components.Interfaces.Bus bus
    "Control bus"
end PartialChiller;


Interface class for coil

within Buildings.Templates.Components.Interfaces;
partial model PartialCoil "Interface class for coil"
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
    redeclare final package Medium=MediumAir,
    final m_flow_nominal=mAir_flow_nominal,
    final allowFlowReversal=allowFlowReversalAir)

  replaceable package MediumAir=Buildings.Media.Air
    "Air medium"
  /*
  The following definition is needed only for Dymola that does not allow
  port_aSou and port_bSou to be instantiated without redeclaring their medium
  to a non-partial class (which is done only in the derived class).
  */
  replaceable package MediumSou=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Source-side medium"

  parameter Buildings.Templates.Components.Types.Coil typ
    "Equipment type"
  parameter Buildings.Templates.Components.Types.Valve typVal
    "Type of valve"
  final parameter Boolean have_sou=
    typ==Buildings.Templates.Components.Types.Coil.WaterBasedHeating or
    typ==Buildings.Templates.Components.Types.Coil.WaterBasedCooling
    "Set to true for fluid ports on the source side"
  final parameter Boolean have_weaBus=
    typ==Buildings.Templates.Components.Types.Coil.EvaporatorMultiStage or
    typ==Buildings.Templates.Components.Types.Coil.EvaporatorVariableSpeed
    "Set to true to use a weather bus"

  parameter Buildings.Templates.Components.Data.Coil dat(
    final have_sou=have_sou,
    final typ=typ,
    final typVal=typVal)
    "Design and operating parameters"

  final parameter Modelica.Units.SI.MassFlowRate mAir_flow_nominal(
    final min=0) = dat.mAir_flow_nominal
    "Air mass flow rate";
  final parameter Modelica.Units.SI.PressureDifference dpAir_nominal(
    final min=0,
    displayUnit="Pa") = dat.dpAir_nominal
    "Air pressure drop";
  final parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=
    dat.Q_flow_nominal
    "Nominal heat flow rate";

  parameter Modelica.Units.SI.Time tau=20
    "Time constant at nominal flow"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=
    Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"

  parameter Boolean allowFlowReversalAir=true
    "= true to allow flow reversal, false restricts to design direction - Air side"
  parameter Boolean allowFlowReversalLiq=true
    "= true to allow flow reversal, false restricts to design direction - CHW and HW side"

  Modelica.Fluid.Interfaces.FluidPort_a port_aSou(
    redeclare final package Medium = MediumSou,
    m_flow(min=if allowFlowReversalLiq then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumSou.h_default, nominal=MediumSou.h_default))
    if have_sou
    "Fluid connector a (positive design flow direction is from port_a to port_b)"
  Modelica.Fluid.Interfaces.FluidPort_b port_bSou(
    redeclare final package Medium = MediumSou,
    m_flow(max=if allowFlowReversalLiq then +Modelica.Constants.inf else 0),
    h_outflow(start = MediumSou.h_default, nominal = MediumSou.h_default))
    if have_sou
    "Fluid connector b (positive design flow direction is from port_a to port_b)"
  Buildings.BoundaryConditions.WeatherData.Bus busWea if have_weaBus
    "Weather bus"
  Buildings.Templates.Components.Interfaces.Bus bus
    if typ <> Buildings.Templates.Components.Types.Coil.None
    "Control bus"

protected
  parameter Buildings.Templates.Components.Data.Valve datVal(
    final typ=typVal,
    final m_flow_nominal=dat.mWat_flow_nominal,
    final dpValve_nominal=dat.dpValve_nominal,
    final dpFixed_nominal=if typVal <> Buildings.Templates.Components.Types.Valve.None
      then dat.dpWat_nominal else 0)
    "Local record for control valve with lumped flow resistance";
initial equation
  if typ==Buildings.Templates.Components.Types.Coil.EvaporatorMultiStage or
    typ==Buildings.Templates.Components.Types.Coil.EvaporatorVariableSpeed then
    assert(mAir_flow_nominal<=dat.datCoi.sta[dat.datCoi.nSta].nomVal.m_flow_nominal,
      "In "+ getInstanceName() + ": "+
      "The coil design airflow ("+String(mAir_flow_nominal)+
      ") exceeds the maximum airflow provided in the performance data record ("+
      String(dat.datCoi.sta[dat.datCoi.nSta].nomVal.m_flow_nominal)+").",
      level=AssertionLevel.warning);
    assert(abs(Q_flow_nominal)<=abs(dat.datCoi.sta[dat.datCoi.nSta].nomVal.Q_flow_nominal),
      "In "+ getInstanceName() + ": "+
      "The coil design capacity ("+String(Q_flow_nominal)+
      ") exceeds the maximum capacity provided in the performance data record ("+
      String(dat.datCoi.sta[dat.datCoi.nSta].nomVal.Q_flow_nominal)+").",
      level=AssertionLevel.warning);
  end if;
end PartialCoil;


Interface class for fan

within Buildings.Templates.Components.Interfaces;
partial model PartialFan "Interface class for fan"
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
    final m_flow_nominal=dat.m_flow_nominal)

  parameter Buildings.Templates.Components.Types.Fan typ
    "Equipment type"
  parameter Boolean have_senFlo = false
    "Set to true for air flow measurement"

  parameter Modelica.Units.SI.Time tau=1
    "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"

  parameter Buildings.Templates.Components.Types.FanSingle typSin=
    Buildings.Templates.Components.Types.FanSingle.Housed
    "Type of single fan"
  parameter Integer text_rotation = 0
    "Text rotation angle in icon layer"
  parameter Boolean text_flip = false
    "True to flip text horizontally in icon layer"

  parameter Buildings.Templates.Components.Data.Fan dat(
    final typ=typ,
    final nFan=nFan)
    "Design and operating parameters"

  parameter Integer nFan(
    final min=0,
    start=0)
    "Number of fans"
  final parameter Modelica.Units.SI.PressureDifference dp_nominal=dat.dp_nominal
    "Total pressure rise";

  Buildings.Templates.Components.Interfaces.Bus bus
    if typ <> Buildings.Templates.Components.Types.Fan.None
    "Control bus"
  Buildings.Templates.Components.Sensors.VolumeFlowRate V_flow(
    redeclare final package Medium = Medium,
    final have_sen=have_senFlo,
    final m_flow_nominal=m_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorVolumeFlowRate.AFMS)
    "Air volume flow rate sensor"
equation
  /* Control point connection - start */
  connect(V_flow.y, bus.V_flow);
  /* Control point connection - stop */
  connect(port_b, V_flow.port_b)
end PartialFan;


HW medium

within Buildings.Templates.Components.Interfaces;
model PartialHeatPump
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
    redeclare final package Medium=MediumHeaWat,
    final m_flow_nominal=max(mHeaWat_flow_nominal, mChiWat_flow_nominal));

  replaceable package MediumHeaWat=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "HW medium"
  /*
  MediumChiWat is for internal use only.
  It is the same as MediumHeaWat for reversible HP.
  Non-reversible HP that can be controlled to produce either HW or CHW
  shall be modeled with chiller components (as a chiller/heater).
  */
  final package MediumChiWat=MediumHeaWat
    "CHW medium";
  /*
  Derived classes representing AWHP shall use:
  redeclare final package MediumSou = MediumAir
  */
  replaceable package MediumSou=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Source-side medium"
  replaceable package MediumAir=Buildings.Media.Air
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Air medium"

  parameter Buildings.Templates.Components.Types.HeatPump typ
    "Equipment type"
  parameter Boolean is_rev
    "Set to true for reversible heat pumps, false for heating only"
  parameter Buildings.Templates.Components.Types.HeatPumpModel typMod=
    Buildings.Templates.Components.Types.HeatPumpModel.EquationFit
    "Type of heat pump model"

  parameter Buildings.Templates.Components.Data.HeatPump dat(
    typ=typ,
    is_rev=is_rev,
    typMod=typMod,
    cpHeaWat_default=cpHeaWat_default,
    cpSou_default=cpSou_default)
    "Design and operating parameters"

  final parameter Modelica.Units.SI.MassFlowRate mHeaWat_flow_nominal=
    dat.mHeaWat_flow_nominal
    "Design HW mass flow rate";
  final parameter Modelica.Units.SI.HeatFlowRate capHea_nominal=
    dat.capHea_nominal
    "Design heating capacity";
  final parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal=
    abs(capHea_nominal)
    "Design heating heat flow rate";
  final parameter Modelica.Units.SI.PressureDifference dpHeaWat_nominal=
    dat.dpHeaWat_nominal
    "Design HW pressure drop";
  final parameter Modelica.Units.SI.Temperature THeaWatSup_nominal=
    dat.THeaWatSup_nominal
    "Design HW supply temperature";
  final parameter Modelica.Units.SI.Temperature THeaWatRet_nominal=
    dat.THeaWatRet_nominal
    "Design HW return temperature";
  final parameter Modelica.Units.SI.MassFlowRate mChiWat_flow_nominal=
    dat.mChiWat_flow_nominal
    "Design CHW mass flow rate"
  final parameter Modelica.Units.SI.PressureDifference dpChiWat_nominal=
    dat.dpChiWat_nominal
    "Design CHW pressure drop";
  final parameter Modelica.Units.SI.HeatFlowRate capCoo_nominal=
    dat.capCoo_nominal
    "Design cooling capacity";
  final parameter Modelica.Units.SI.HeatFlowRate QCoo_flow_nominal=
    -abs(capCoo_nominal)
    "Design cooling heat flow rate";
  final parameter Modelica.Units.SI.Temperature TChiWatSup_nominal=
    dat.TChiWatSup_nominal
    "Design CHW supply temperature";
  final parameter Modelica.Units.SI.Temperature TChiWatRet_nominal=
    dat.TChiWatRet_nominal
    "Design CHW return temperature";
  final parameter Modelica.Units.SI.MassFlowRate mSouHea_flow_nominal=
    dat.mSouHea_flow_nominal
    "Design source fluid mass flow rate in heating mode";
  final parameter Modelica.Units.SI.PressureDifference dpSouHea_nominal=
    dat.dpSouHea_nominal
    "Design source fluid pressure drop in heating mode";
  final parameter Modelica.Units.SI.MassFlowRate mSouCoo_flow_nominal=
    dat.mSouCoo_flow_nominal
    "Design source fluid mass flow rate in cooling mode";
  final parameter Modelica.Units.SI.PressureDifference dpSouCoo_nominal=
    dat.dpSouCoo_nominal
    "Designs source fluid pressure drop in cooling mode";
  final parameter Modelica.Units.SI.Temperature TSouCoo_nominal=
    dat.TSouCoo_nominal
    "Design OAT or source fluid supply temperature (condenser entering) in cooling mode";
  final parameter Modelica.Units.SI.Temperature TSouHea_nominal=
    dat.TSouHea_nominal
    "Design OAT or source fluid supply temperature (evaporator entering) in heating mode";

  parameter Modelica.Fluid.Types.Dynamics energyDynamics=
    Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  parameter Boolean allowFlowReversalSou = true
    "Source side flow reversal: false to simplify equations, assuming, but not enforcing, no flow reversal"
  parameter Boolean have_dpChiHeaWat=true
    "Set to true for CHW/HW pressure drop computed by this model, false for external computation"
  parameter Boolean have_dpSou=true
    "Set to true for source fluid pressure drop computed by this model, false for external computation"

  final parameter MediumHeaWat.SpecificHeatCapacity cpHeaWat_default=
    MediumHeaWat.specificHeatCapacityCp(staHeaWat_default)
    "HW default specific heat capacity";
  final parameter MediumHeaWat.ThermodynamicState staHeaWat_default=
    MediumHeaWat.setState_pTX(
      T=THeaWatSup_nominal,
      p=MediumHeaWat.p_default,
      X=MediumHeaWat.X_default)
    "HW default state";
  final parameter MediumChiWat.SpecificHeatCapacity cpChiWat_default=
    MediumChiWat.specificHeatCapacityCp(staChiWat_default)
    "CHW default specific heat capacity";
  final parameter MediumChiWat.ThermodynamicState staChiWat_default=
    MediumChiWat.setState_pTX(
      T=TChiWatSup_nominal,
      p=MediumChiWat.p_default,
      X=MediumChiWat.X_default)
    "CHW default state";
  final parameter MediumSou.SpecificHeatCapacity cpSou_default=
    MediumSou.specificHeatCapacityCp(staSou_default)
    "Source fluid default specific heat capacity";
  final parameter MediumSou.ThermodynamicState staSou_default=
    MediumSou.setState_pTX(
      T=TSouHea_nominal,
      p=MediumSou.p_default,
      X=MediumSou.X_default)
    "Source fluid default state";

  Modelica.Fluid.Interfaces.FluidPort_a port_aSou(
    redeclare final package Medium = MediumSou)
    "Fluid connector a (positive design flow direction is from port_a to port_b)"
  Modelica.Fluid.Interfaces.FluidPort_b port_bSou(
    redeclare final package Medium = MediumSou)
    "Fluid connector b (positive design flow direction is from port_a to port_b)"
  Buildings.Templates.Components.Interfaces.Bus bus
    "Control bus"
  Buildings.BoundaryConditions.WeatherData.Bus busWea
    if typ==Buildings.Templates.Components.Types.HeatPump.AirToWater
    "Weather bus"
  Fluid.Sources.Outside air(
    redeclare final package Medium = MediumAir,
    nPorts=2)
    if typ == Buildings.Templates.Components.Types.HeatPump.AirToWater
    "Outdoor air"

  // Diagnostics
  MediumSou.ThermodynamicState sta_aSou=
      MediumSou.setState_phX(port_aSou.p,
                          noEvent(actualStream(port_aSou.h_outflow)),
                          noEvent(actualStream(port_aSou.Xi_outflow)))
      if show_T "Source medium properties in port_aSou";
  MediumSou.ThermodynamicState sta_bSou=
      MediumSou.setState_phX(port_bSou.p,
                          noEvent(actualStream(port_bSou.h_outflow)),
                          noEvent(actualStream(port_bSou.Xi_outflow)))
      if show_T "Source medium properties in port_bSou";
equation
  connect(busWea, air.weaBus)
  connect(port_aSou, air.ports[1])
  connect(port_bSou, air.ports[2])
end PartialHeatPump;


within Buildings.Templates.Components.Interfaces;
model PartialHeatPumpEquationFit
  "Interface for heat pump using equation fit model"
  extends Buildings.Templates.Components.Interfaces.PartialHeatPump(
    final typMod=Buildings.Templates.Components.Types.HeatPumpModel.EquationFit);

  final parameter Buildings.Fluid.HeatPumps.Data.EquationFitReversible.Generic datPerFit(
    dpHeaSou_nominal = if have_dpSou then dat.perFit.dpHeaSou_nominal else 0,
    dpHeaLoa_nominal = if have_dpChiHeaWat then dat.perFit.dpHeaLoa_nominal else 0,
    hea(
      TRefLoa = dat.perFit.hea.TRefLoa,
      TRefSou = dat.perFit.hea.TRefSou,
      Q_flow = dat.perFit.hea.Q_flow,
      P = dat.perFit.hea.P,
      mSou_flow = dat.perFit.hea.mSou_flow,
      mLoa_flow = dat.perFit.hea.mLoa_flow,
      coeQ = dat.perFit.hea.coeQ,
      coeP = dat.perFit.hea.coeP),
    coo(
      TRefSou = dat.perFit.coo.TRefSou,
      TRefLoa =  dat.perFit.coo.TRefLoa,
      Q_flow = dat.perFit.coo.Q_flow,
      P = dat.perFit.coo.P,
      coeQ = dat.perFit.coo.coeQ,
      coeP = dat.perFit.coo.coeP))
  "Performance data - Equation fit model";

  Modelica.Blocks.Routing.BooleanPassThrough y1Hea if is_rev
    "Operating mode command: true=heating, false=cooling"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant y1HeaNonRev(
    final k=true) if not is_rev
    "Placeholder signal for non-reversible heat pumps"
  Controls.StatusEmulator y1_actual
    "Compute heat pump status"
  Fluid.Sensors.MassFlowRate mChiHeaWat_flow(redeclare final package Medium =
        MediumHeaWat) "CHW/HW mass flow rate"
  Fluid.Sensors.TemperatureTwoPort TChiHeaWatEnt(redeclare final package Medium =
        MediumHeaWat, final m_flow_nominal=max(mChiWat_flow_nominal,
        mHeaWat_flow_nominal)) "CHW/HW entering temperature"
  Fluid.Sensors.TemperatureTwoPort TChiHeaWatLvg(redeclare final package Medium =
        MediumHeaWat, final m_flow_nominal=max(mChiWat_flow_nominal,
        mHeaWat_flow_nominal)) "CHW/HW leaving temperature"
  Fluid.Sensors.TemperatureTwoPort TSouEnt(
    redeclare final package Medium = MediumSou, final m_flow_nominal=
        mSouHea_flow_nominal) "Source fluid entering temperature"
  Fluid.Sensors.TemperatureTwoPort TSouLvg(
    redeclare final package Medium = MediumSou,
    final m_flow_nominal=
        mSouHea_flow_nominal) "Source fluid leaving temperature"
  Buildings.Fluid.HeatPumps.EquationFitReversible hp(
    uMod(start=0),
    redeclare final package Medium1 = MediumHeaWat,
    redeclare final package Medium2 = MediumSou,
    final per=datPerFit,
    final energyDynamics=energyDynamics) "Heat pump"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger y1Int
    "Convert on/off command into integer"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToInteger y1HeaInt(
    y(start=0),
    final integerTrue=1,
    final integerFalse=-1)
    "Convert heating mode command into integer"
  Buildings.Controls.OBC.CDL.Integers.Multiply mulInt
    "Combine on/off and operating mode command signals"
equation
  /* Control point connection - start */
  /* Control point connection - stop */
  connect(bus.y1Hea, y1Hea.u)
  connect(port_a, mChiHeaWat_flow.port_a)
  connect(mChiHeaWat_flow.port_b, TChiHeaWatEnt.port_a)
  connect(TChiHeaWatLvg.port_b, port_b)
  connect(TSouLvg.port_b, port_bSou)
  connect(y1Hea.y, y1HeaInt.u)
  connect(y1HeaNonRev.y, y1HeaInt.u)
  connect(y1HeaInt.y, mulInt.u2)
  connect(y1Int.y, mulInt.u1)
  connect(TChiHeaWatEnt.port_b, hp.port_a1)
  connect(hp.port_b1, TChiHeaWatLvg.port_a)
  connect(TSouLvg.port_a, hp.port_b2)
  connect(TSouEnt.port_b, hp.port_a2)
  connect(bus.y1, y1Int.u)
  connect(bus.TSet, hp.TSet)
  connect(mulInt.y, hp.uMod)
  connect(y1_actual.y1_actual, bus.y1_actual)
  connect(bus.y1, y1_actual.y1)
end PartialHeatPumpEquationFit;


Base class for all pump models. This partial class provides a standard interface for pump models.

within Buildings.Templates.Components.Interfaces;
model PartialPump "Base class for all pump models"
  parameter Buildings.Templates.Components.Types.Pump typ
    "Equipment type"

  parameter Boolean have_var=true
    "Set to true for variable speed pump, false for constant speed pump"
  parameter Boolean have_varCom=true
    "Set to true for single common speed signal, false for dedicated signals"

  parameter Boolean have_valChe=true
    "Set to true to include a check valve in pump line"

  parameter Boolean addPowerToMedium=false
    "Set to false to avoid any power (=heat and flow work) being added to medium (may give simpler equations)"

  parameter Modelica.Units.SI.Time tau=1
    "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"
  parameter Boolean allowFlowReversal = true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal"

  parameter Integer text_rotation = 0
    "Text rotation angle in icon layer"
  parameter Boolean text_flip = false
    "True to flip text horizontally in icon layer"

  Buildings.Templates.Components.Interfaces.Bus bus
    "Control bus"
end PartialPump;


within Buildings.Templates.Components.Interfaces;
partial model PartialPumpMultiple
  "Interface class for multiple pumps in parallel arrangement"
  extends Buildings.Templates.Components.Interfaces.PartialPump;

  replaceable package Medium=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Medium in the component"

  parameter Integer nPum(
    final min=0,
    start=1)
    "Number of pumps"

  parameter Buildings.Templates.Components.Data.PumpMultiple dat(
    final nPum=nPum,
    final typ=typ)
    "Design and operating parameters"

  final parameter Modelica.Units.SI.MassFlowRate m_flow_nominal[nPum](
    each final min=0)=dat.m_flow_nominal
    "Nominal mass flow rate"
  final parameter Modelica.Units.SI.PressureDifference dp_nominal[nPum](
    each final min=0,
    each displayUnit="Pa")=dat.dp_nominal
    "Pump head at design conditions"
  // This parameter is declared outside the parameter record dat as
  // it is considered to be an advanced parameter for which a default
  // value can probably be used.
  parameter Modelica.Units.SI.PressureDifference dpValChe_nominal[nPum](
    each final min=0,
    each start=Buildings.Templates.Data.Defaults.dpValChe,
    each displayUnit="Pa")=fill(Buildings.Templates.Data.Defaults.dpValChe, nPum)
    "Check valve pressure drop at design conditions"
  Modelica.Fluid.Interfaces.FluidPorts_a ports_a[nPum](
    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),
    each p(start=Medium.p_default))
     "Vectorized fluid connector a (positive design flow direction is from port(s)_a to port(s)_b)"
  Modelica.Fluid.Interfaces.FluidPorts_b ports_b[nPum](
    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),
    each p(start=Medium.p_default))
     "Vectorized fluid connector b (positive design flow direction is from port(s)_a to port(s)_b)"

  parameter Integer icon_dy = 300
    "Distance in y-direction between each unit in icon layer"

end PartialPumpMultiple;


Interface class for single pump

within Buildings.Templates.Components.Interfaces;
partial model PartialPumpSingle "Interface class for single pump"
  extends Buildings.Templates.Components.Interfaces.PartialPump;
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
    redeclare replaceable package Medium=Buildings.Media.Water,
    final m_flow_nominal(min=0)=dat.m_flow_nominal)

  parameter Buildings.Templates.Components.Data.PumpSingle dat(
    final typ=typ)
    "Design and operating parameters"

  final parameter Modelica.Units.SI.PressureDifference dp_nominal(
    final min=0,
    displayUnit="Pa")=dat.dp_nominal
    "Pump head at design conditions"

  // This parameter is declared outside the parameter record dat as
  // it is considered to be an advanced parameter for which a default
  // value can probably be used.
  parameter Modelica.Units.SI.PressureDifference dpValChe_nominal(
    final min=0,
    start=Buildings.Templates.Data.Defaults.dpValChe,
    displayUnit="Pa")=Buildings.Templates.Data.Defaults.dpValChe
    "Check valve pressure drop at design conditions"
end PartialPumpSingle;


Interface class for sensor. This partial class provides a standard interface for sensor models.

within Buildings.Templates.Components.Interfaces;
partial model PartialSensor "Interface class for sensor"
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface

  parameter Boolean have_sen=true
    "Set to true for sensor, false for direct pass through"
  parameter Boolean isDifPreSen=false
    "Set to true for differential pressure sensor, false for any other sensor"

  parameter Integer text_rotation = 0
    "Text rotation angle in icon layer"
  parameter Boolean text_flip = false
    "True to flip text horizontally in icon layer"
  parameter Buildings.Templates.Components.Types.IntegrationPoint icon_pipe=
      Buildings.Templates.Components.Types.IntegrationPoint.None "Pipe symbol"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput y if have_sen
    "Connector for measured value"

equation
  if isDifPreSen and (not have_sen) then
    // Zero flow equations for connectors
    port_a.m_flow = 0;
    port_b.m_flow = 0;

    // No contribution of specific quantities
    port_a.h_outflow = 0;
    port_b.h_outflow = 0;
    port_a.Xi_outflow = zeros(Medium.nXi);
    port_b.Xi_outflow = zeros(Medium.nXi);
    port_a.C_outflow  = zeros(Medium.nC);
    port_b.C_outflow  = zeros(Medium.nC);
  end if;
end PartialSensor;