Injection circuit with two-way valve

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks;
model InjectionTwoWay "Injection circuit with two-way valve"
  extends HydronicConfigurations.Interfaces.PartialHydronicConfiguration(
    set(final unit="K", displayUnit="degC"),
    dpValve_nominal=dp1_nominal / 2,
    final dpBal3_nominal=0,
    final typVal=Buildings.Fluid.HydronicConfigurations.Types.Valve.TwoWay,
    final have_typVar=true,
    final use_dp1=use_siz,
    final use_dp2=use_siz and typPum<>Buildings.Fluid.HydronicConfigurations.Types.Pump.None);

  FixedResistances.Junction junSup(
    redeclare final package Medium = Medium,
    final energyDynamics=energyDynamics,
    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,
    final m_flow_nominal=m2_flow_nominal .* {1,-1,1},
    final dp_nominal=fill(0, 3))
    "Junction"
  Components.Pump pum(
    redeclare final package Medium = Medium,
    final typ=typPum,
    final typMod=typPumMod,
    final m_flow_nominal=mPum_flow_nominal,
    final dp_nominal=dpPum_nominal,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    use_riseTime=energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState,
    final per=perPum) "Pump"
  Components.TwoWayValve val(
    redeclare final package Medium = Medium,
    final typCha=typCha,
    use_strokeTime=energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m1_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal=if use_lumFloRes then dpBal1_nominal else 0,
    final flowCharacteristics=flowCharacteristics)
    "Control valve"
  Sensors.TemperatureTwoPort T2Sup(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m2_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    tau=if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState then 0
         else 1) "Consumer circuit supply temperature sensor"
  FixedResistances.Junction junRet(
    redeclare final package Medium = Medium,
    final energyDynamics=energyDynamics,
    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,
    final m_flow_nominal=m2_flow_nominal .* {1,-1,-1},
    final dp_nominal=fill(0, 3))
    "Junction"
  FixedResistances.PressureDrop res2(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m2_flow_nominal,
    final dp_nominal=dpBal2_nominal)
    "Secondary balancing valve"
  FixedResistances.PressureDrop res1(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m1_flow_nominal,
    final dp_nominal=if use_lumFloRes then 0 else dpBal1_nominal)
    "Primary balancing valve"
  Sensors.TemperatureTwoPort T2Ret(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m2_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    tau=if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState then 0
         else 1) "Consumer circuit return temperature sensor"
  Controls.PIDWithOperatingMode ctl(
    u_s(final unit="K", displayUnit="degC"),
    u_m(final unit="K", displayUnit="degC"),
    final reverseActing=typCtl == Buildings.Fluid.HydronicConfigurations.Types.Control.Heating,
    final yMin=0,
    final yMax=1,
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti) if typCtl<>Buildings.Fluid.HydronicConfigurations.Types.Control.None
    "Controller"

  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold isEna(final t=Controls.OperatingModes.disabled)
    "Returns true if enabled"
  Buildings.Controls.OBC.CDL.Routing.RealExtractor extIndSig(final nin=2)
    "Select measured signal"
  replaceable FixedResistances.LosslessPipe res3(
    redeclare final package Medium =Medium,
    m_flow_nominal=m2_flow_nominal)
    "Fluid pass-through that can be replaced by check valve"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant ctlVar(
    final k=Integer(typVar))
    "Controlled variable selector"

initial equation
  if m2_flow_nominal <= m1_flow_nominal then
    Modelica.Utilities.Streams.print(
      "*** Warning: In " + getInstanceName() +
      ": Primary mass flow rate should be strictly lower than consumer circuit mass flow rate " +
      "at design conditions to ensure an actual variable flow in the primary.");
  end if;

  if typPum==Buildings.Fluid.HydronicConfigurations.Types.Pump.VariableInput and
    typVar==Buildings.Fluid.HydronicConfigurations.Types.ControlVariable.ReturnTemperature then
    Modelica.Utilities.Streams.print(
      "*** Warning: In " + getInstanceName() +
      ": Return temperature control is likely not compatible with a variable flow consumer circuit.");
  end if;
equation
  connect(junSup.port_2, pum.port_a)
  connect(junSup.port_1, port_a1)
  connect(pum.port_b, T2Sup.port_a)
  connect(T2Sup.port_b, port_b2)
  connect(junRet.port_1,res2. port_b)
  connect(val.port_b,res1. port_a)
  connect(res1.port_b, port_b1)
  connect(res2.port_a, T2Ret.port_b)
  connect(T2Ret.port_a, port_a2)
  connect(ctl.y, val.y)
  connect(set, ctl.u_s)
  connect(mode, isEna.u)
  connect(T2Sup.T, extIndSig.u[2])
  connect(T2Ret.T, extIndSig.u[1])
  connect(junRet.port_2, val.port_a)
  connect(extIndSig.y, ctl.u_m)
  connect(mode, ctl.mode)
  connect(junRet.port_3, res3.port_a)
  connect(res3.port_b, junSup.port_3)
  connect(ctlVar.y, extIndSig.index)
  connect(yVal, val.y)
  connect(pum.P, PPum)
  connect(pum.y_actual, yPum_actual)
  connect(val.y_actual, yVal_actual)
  connect(isEna.y, pum.y1)
  connect(yPum, pum.y)
end InjectionTwoWay;


Injection circuit with two-way valve and check valve in bypass branch.

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks;
model InjectionTwoWayCheckValve
  "Injection circuit with two-way valve and check valve in bypass branch"
  extends Fluid.HydronicConfigurations.ActiveNetworks.InjectionTwoWay(
    dpPum_nominal=dp2_nominal + dpBal2_nominal + res3.dpValve_nominal,
    redeclare FixedResistances.CheckValve res3(
      final dpValve_nominal=5e3,
      final allowFlowReversal=allowFlowReversal,
      final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
      final dpFixed_nominal=0));
end InjectionTwoWayCheckValve;


within Buildings.Fluid.HydronicConfigurations;
package ActiveNetworks "Package of hydronic configurations for active networks"
  extends Modelica.Icons.VariantsPackage;
end ActiveNetworks;


Single mixing circuit.

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks;
model SingleMixing "Single mixing circuit"
  extends BaseClasses.SingleMixing(
    final dpBal3_nominal=0);

end SingleMixing;


Throttle circuit

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks;
model Throttle "Throttle circuit"
  extends Fluid.HydronicConfigurations.Interfaces.PartialHydronicConfiguration(
    dpValve_nominal=dp2_nominal + dpBal1_nominal,
    final dpBal2_nominal=0,
    final dpBal3_nominal=0,
    final m1_flow_nominal=m2_flow_nominal,
    final typVal=Buildings.Fluid.HydronicConfigurations.Types.Valve.TwoWay,
    final typPum=Buildings.Fluid.HydronicConfigurations.Types.Pump.None,
    final typCtl=Buildings.Fluid.HydronicConfigurations.Types.Control.None,
    final have_typVar=false,
    final use_dp1=false,
    final use_dp2=use_lumFloRes or use_siz);

  Buildings.Fluid.HydronicConfigurations.Components.TwoWayValve val(
    redeclare final package Medium=Medium,
    final typCha=typCha,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m2_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal=if use_lumFloRes then dpBal1_nominal + dp2_nominal else 0,
    final flowCharacteristics=flowCharacteristics)
    "Control valve"
  Buildings.Fluid.FixedResistances.PressureDrop res1(
    redeclare final package Medium=Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m1_flow_nominal,
    final dp_nominal=if use_lumFloRes then 0 else dpBal1_nominal)
    "Primary balancing valve"
equation
  connect(res1.port_b, port_b1)
  connect(port_b2, port_a1)

  connect(val.port_b,res1. port_a)
  connect(val.port_a, port_a2)
  connect(yVal, val.y)
  connect(val.y_actual, yVal_actual)
end Throttle;


Model illustrating the operation of a decoupling circuit. This model represents a change-over system where the configuration

Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Decoupling
serves as the interface between a variable flow primary circuit
and a variable flow consumer circuit operated in change-over.
For a given operating mode, both the primary circuit and the
consumer circuit have a constant supply temperature.

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
model Decoupling
  "Model illustrating the operation of a decoupling circuit"
  extends BaseClasses.PartialDecoupling(del2(nPorts=4), mode(table=[0,0; 6,0; 6,
          2; 15,2; 15,1; 22,1; 22,0; 24,0]),
    T1Set(nin=3));

equation
  connect(con.port_b2, jun.port_1)
  connect(con.port_a2, del2.ports[4])
end Decoupling;


within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
model DecouplingMixing
  "Model illustrating the operation of a decoupling circuit serving a single mixing circuit"
  extends
    Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.PartialDecoupling(
    ctlPum2(k=0.1, r=1e4),
    typ=Buildings.Fluid.HydronicConfigurations.Types.Control.Cooling,
    con(typPum=Buildings.Fluid.HydronicConfigurations.Types.Pump.None),
    mode(table=[0,0; 6,0; 6,1; 15,1; 15,1; 22,1; 22,0; 24,0]),
    del2(nPorts=4));

  PassiveNetworks.SingleMixing con1(
    typPum=Buildings.Fluid.HydronicConfigurations.Types.Pump.VariableInput,
    redeclare final package Medium=MediumLiq,
    typCtl=typ,
    final energyDynamics=energyDynamics,
    final m2_flow_nominal=m2_flow_nominal,
    final dp2_nominal=dp2_nominal,
    dp1_nominal=con.dpBal3_nominal)
    "Single mixing connection"
  Controls.PIDWithOperatingMode resT2(
    k=1,
    Ti=60,
    reverseActing=false,
    y_reset=1) "PI controller for consumer circuit temperature reset"
  Buildings.Controls.OBC.CDL.Reals.Line T2SetVar(
    y(final unit="K", displayUnit="degC"))
    "Consumer circuit temperature set point (reset)"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yValSet(k=0.9, y(
        final unit="1"))
    "Valve opening set point"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(final k=1.0,
                                                                        y(
        final unit="1"))
    "One"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer1(final k=0.0,
                                                                         y(
        final unit="1"))
    "Zero"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant T2SetLim0(k=
    TLiqEnt_nominal + 5,
    y(final unit="K", displayUnit="degC"))
    "Consumer circuit temperature limiting set point "
  Buildings.Controls.OBC.CDL.Reals.Max yValMax(
    y(final unit="1"))
    "Maximum valve opening"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant T2SetLim1(
    final k=TLiqEnt_nominal,
    y(final unit="K", displayUnit="degC"))
    "Consumer circuit temperature design set point "
equation
  connect(resT2.y,T2SetVar. u)
  connect(yValSet.y,resT2. u_s)
  connect(zer1.y, T2SetVar.x1)
  connect(one.y,T2SetVar. x2)
  connect(T2SetLim0.y,T2SetVar. f1)
  connect(yValMax.y, resT2.u_m)
  connect(T2SetVar.y, con1.set)
  connect(T2SetLim1.y, T2SetVar.f2)
  connect(con.port_b2, con1.port_a1)
  connect(con.port_a2, con1.port_b1)
  connect(loa.yVal_actual, yValMax.u2)
  connect(loa1.yVal_actual, yValMax.u1)
  connect(mode.y[1], con1.mode)
  connect(ctlPum2.y, con1.yPum)
  connect(mode.y[1], resT2.mode)
  connect(con1.port_b2, jun.port_1)
  connect(con1.port_a2, del2.ports[4])
end DecouplingMixing;


Model illustrating the operation of a decoupling circuit with Delta-T control. This example is similar to

Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.Decoupling
except that an alternative control logic is implemented,
based on the measurement of the return temperature in the consumer circuit
and in the primary branch.

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
model DecouplingTemperature
  "Model illustrating the operation of a decoupling circuit with Delta-T control"
  extends
    Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.Decoupling(
      con(typCtl=Buildings.Fluid.HydronicConfigurations.Types.Control.None,
          dpBal3_nominal=0));

  parameter Boolean is_cor = false
    "Set to true to correct Delta-T set point for low load operation"

  Buildings.Controls.OBC.CDL.Reals.Subtract dT(
    y(final unit="K")) "Compute T1Ret-T2Ret"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dTSetVal[3](final k={1,
        if typ == Types.Control.Heating then 1 else -1,1})
    "Delta-T set point values"
  Buildings.Controls.OBC.CDL.Routing.RealExtractor dTSetAct(
    y(final unit="K"), final nin=3)
                       "Select actual set point based on operating mode"
  Controls.PIDWithOperatingMode ctl(
    k=0.1,
    Ti=120,
    u_s(final unit="K", displayUnit="K"),
    u_m(final unit="K", displayUnit="K"),
    final reverseActing=typ == Buildings.Fluid.HydronicConfigurations.Types.Control.Heating)
    "Controller"
  Buildings.Controls.OBC.CDL.Reals.Subtract dT2SupRet(y(final unit="K"))
    "Compute T2Sup-T2Ret"
  Modelica.Blocks.Sources.RealExpression T2Ret(y=con.T2Ret.T)
    "Access T2Ret measurement from connection component"
  Modelica.Blocks.Sources.RealExpression T2Sup(y=con.T2Sup.T)
    "Access T2Sup measurement from connection component"
  Buildings.Controls.OBC.CDL.Reals.Max maxDelT(y(final unit="K"))
    "Compute max(T2Sup-T2Ret, dTSet) for cooling mode"
  Buildings.Controls.OBC.CDL.Reals.Min minDelT(y(final unit="K"))
    "Compute min(T2Sup-T2Ret, dTSet) for heating mode"
  Buildings.Controls.OBC.CDL.Routing.RealExtractor dTSetCor(
    y(final unit="K"), final nin=3)
                       if is_cor
    "Delta-T set point corrected for low load operation"
  Modelica.Blocks.Routing.RealPassThrough dTSetUnc if not is_cor
    "Delta-T set point uncorrected"
equation

  connect(T1ConRet.T, dT.u1)
  connect(dT.y, ctl.u_m)
  connect(dTSetVal.y, dTSetAct.u)
  connect(ctl.y, con.yVal)
  connect(mode.y[1], ctl.mode)
  connect(T2Ret.y, dT.u2)
  connect(T2Sup.y, dT2SupRet.u1)
  connect(T2Ret.y, dT2SupRet.u2)
  connect(dT2SupRet.y, maxDelT.u2)
  connect(dT2SupRet.y, minDelT.u1)
  connect(dTSetAct.y, maxDelT.u1)
  connect(dTSetAct.y, minDelT.u2)
  connect(dTSetCor.y, ctl.u_s)
  connect(dTSetAct.y, dTSetUnc.u)
  connect(dTSetUnc.y, ctl.u_s)
  connect(addPar.y, dTSetAct.index)
  connect(addPar.y, dTSetCor.index)
  connect(maxDelT.y, dTSetCor.u[2])
  connect(minDelT.y, dTSetCor.u[3])
  connect(dT2SupRet.y, dTSetCor.u[1])
end DecouplingTemperature;


within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
model DiversionOpenLoop "Model illustrating the operation of diversion circuits with constant speed pump"
  extends BaseClasses.PartialActivePrimary(
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    dpPum_nominal=
    (2 * dpPip_nominal + dpTer_nominal + dpValve_nominal) * kSizPum,
    pum(typ=Buildings.Fluid.HydronicConfigurations.Types.Pump.NoVariableInput),
    del1(nPorts=3));

  parameter Boolean is_bal=false
    "Set to true for a balanced bypass"
  parameter Buildings.Fluid.HydronicConfigurations.Types.ValveCharacteristic typCha=
    Buildings.Fluid.HydronicConfigurations.Types.ValveCharacteristic.EqualPercentage
    "Control valve characteristic"
  parameter Modelica.Units.SI.PressureDifference dpValve_nominal(
    final min=0,
    displayUnit="Pa") = dpTer_nominal
    "Control valve pressure drop at design conditions";
  parameter Modelica.Units.SI.PressureDifference dpBal3_nominal(
    final min=0,
    displayUnit="Pa") = if is_bal then dpTer_nominal else 0
    "Bypass balancing valve pressure drop at design conditions"

  ActiveNetworks.Diversion con(
    use_siz=false,
    redeclare final package Medium=MediumLiq,
    val(fraK=1),
    final typCha=typCha,
    final use_lumFloRes=false,
    final energyDynamics=energyDynamics,
    final m2_flow_nominal=mTer_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpBal1_nominal=dpPum_nominal - dpPip_nominal - dpTer_nominal - dpValve_nominal,
    final dpBal3_nominal=dpBal3_nominal)
    "Hydronic connection"
  Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.Load
    loa(
    redeclare final package MediumLiq = MediumLiq,
    final typ=typ,
    final dpLiq_nominal=dpTer_nominal,
    final energyDynamics=energyDynamics,
    final mLiq_flow_nominal=mTer_flow_nominal,
    final TLiqEnt_nominal=TLiqEnt_nominal,
    final TLiqLvg_nominal=TLiqLvg_nominal,
    k=10) "Load"
  .Buildings.Controls.OBC.CDL.Reals.Sources.Constant fraLoa(k=1.0)
    "Load modulating signal"
  ActiveNetworks.Diversion con1(
    use_siz=false,
    redeclare final package Medium = MediumLiq,
    val(fraK=1),
    final typCha=typCha,
    final use_lumFloRes=false,
    final energyDynamics=energyDynamics,
    final m2_flow_nominal=mTer_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpBal1_nominal=dpPum_nominal - 2 * dpPip_nominal - dpTer_nominal - dpValve_nominal,
    final dpBal3_nominal=dpBal3_nominal)
    "Hydronic connection"
  Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.Load
    loa1(
    redeclare final package MediumLiq = MediumLiq,
    final typ=typ,
    final dpLiq_nominal=dpTer_nominal,
    final energyDynamics=energyDynamics,
    final mLiq_flow_nominal=mTer_flow_nominal,
    final TLiqEnt_nominal=TLiqEnt_nominal,
    final TLiqLvg_nominal=TLiqLvg_nominal,
    k=10) "Load"
  FixedResistances.PressureDrop res1b(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=mPum_flow_nominal - mTer_flow_nominal,
    final dp_nominal=dpPip_nominal) "Pipe pressure drop"
  Sensors.RelativePressure dp(
    redeclare final package Medium = MediumLiq)
    "Differential pressure"
  Sensors.RelativePressure dp1(
    redeclare final package Medium = MediumLiq)
    "Differential pressure"
  .Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable ope(
    table=[0,1,1; 1,0,1; 2,1,0; 3,0,0],
    extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.HoldLastPoint,
    timeScale=100) "Valve opening signal"

  Buildings.Controls.OBC.CDL.Integers.Sources.Constant mode(k=1)
    "Operating mode"
  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold isEna(final t=Controls.OperatingModes.disabled)
    "Returns true if enabled"
equation
  connect(con.port_b2, loa.port_a)
  connect(loa.port_b, con.port_a2)
  connect(fraLoa.y, loa.u)
  connect(con1.port_b2, loa1.port_a)
  connect(con1.port_a2, loa1.port_b)
  connect(fraLoa.y, loa1.u)
  connect(dp1.port_a, res1b.port_b)
  connect(dp1.port_a, con1.port_a1)
  connect(con1.port_b1, dp1.port_b)
  connect(con.port_b1, dp.port_b)
  connect(con.port_a1, dp.port_a)
  connect(ope.y[1], con.yVal)
  connect(ope.y[2], con1.yVal)
  connect(res1.port_b, dp.port_a)
  connect(dp.port_b, del1.ports[2])
  connect(res1.port_b, res1b.port_a)
  connect(dp1.port_b, del1.ports[3])
  connect(mode.y, loa.mode)
  connect(mode.y, loa1.mode)
  connect(mode.y, isEna.u)
  connect(isEna.y, pum.y1)
end DiversionOpenLoop;


within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
model InjectionThreeWay
  "Model illustrating the operation of an inversion circuit with three-way valve"
  extends BaseClasses.PartialActivePrimary(
    m1_flow_nominal=
      m2_flow_nominal * (TLiqEnt_nominal - TLiqLvg_nominal) / (TLiqSup_nominal - TLiqLvg_nominal),
    kSizPum=5.0,
    TLiqEnt_nominal=40+273.15,
    TLiqLvg_nominal=TLiqEnt_nominal-5,
    TLiqSup_nominal=60+273.15,
    dpPum_nominal=(dpPip_nominal + con.dpValve_nominal) * kSizPum,
    del1(nPorts=2),
    pum(typ=Buildings.Fluid.HydronicConfigurations.Types.Pump.NoVariableInput));

  parameter Real kSizBal(final min=0) = 0.5
    "Sizing factor for primary balancing valve (1 means balanced)"

  Buildings.Fluid.HydronicConfigurations.ActiveNetworks.InjectionThreeWay con(
    typPum=Buildings.Fluid.HydronicConfigurations.Types.Pump.NoVariableInput,
    redeclare final package Medium = MediumLiq,
    use_lumFloRes=false,
    typCtl=typ,
    final energyDynamics=energyDynamics,
    final m1_flow_nominal=m1_flow_nominal,
    final m2_flow_nominal=m2_flow_nominal,
    final dp2_nominal=dpTer_nominal + loa.con.dpValve_nominal + dpPip_nominal,
    final dpBal1_nominal= kSizBal * (dpPum_nominal - dpPip_nominal - con.dpValve_nominal),
    pum(addPowerToMedium=false))
    "Hydronic connection"

  Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.LoadThreeWayValveControl
    loa(
    redeclare final package MediumLiq = MediumLiq,
    final typ=typ,
    k=0.1,
    final energyDynamics=energyDynamics,
    final mLiq_flow_nominal=mTer_flow_nominal,
    final TLiqEnt_nominal=TLiqEnt_nominal,
    final TLiqLvg_nominal=TLiqLvg_nominal)
    "Load"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable fraLoa(table=[0,0,0;
        6,0,0; 6.1,1,1; 8,1,1; 9,1,0; 14,0.5,0; 14.5,0,0; 16,0,0; 17,0,1; 21,0,
        1; 22,0,0; 24,0,0],
    timeScale=3600)
    "Load modulating signal"
  Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.LoadThreeWayValveControl
    loa1(
    redeclare final package MediumLiq = MediumLiq,
    final typ=typ,
    k=0.1,
    final energyDynamics=energyDynamics,
    final mLiq_flow_nominal=mTer_flow_nominal,
    final TLiqEnt_nominal=TLiqEnt_nominal,
    final TLiqLvg_nominal=TLiqLvg_nominal)
    "Load"
  Sensors.RelativePressure dp(
    redeclare final package Medium = MediumLiq)
    "Differential pressure"
  FixedResistances.PressureDrop res2(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=con.pum.m_flow_nominal - loa.mLiq_flow_nominal,
    final dp_nominal=dpPip_nominal)
    "Pipe pressure drop"
  Buildings.Controls.OBC.CDL.Integers.Sources.TimeTable mode(
    table=[0,0; 6,0; 6,1; 22,1; 22,0; 24,0],
    timeScale=3600,
    period=86400) "Operating mode (time schedule)"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable setOff(table=[0,0; 12,
        0; 13,-5; 14,-7; 17,0; 24,0],  timeScale=3600)
    "Offset applied to design supply temperature to compute set point"
  Buildings.Controls.OBC.CDL.Reals.AddParameter T2Set(final p=
        TLiqEnt_nominal, y(final unit="K", displayUnit="degC"))
    "Consumer circuit temperature set point"
  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold isEna(final t=Controls.OperatingModes.disabled)
    "Returns true if enabled"
equation
  connect(con.port_b1, dp.port_b)
  connect(con.port_a1, dp.port_a)
  connect(res2.port_b, loa1.port_a)
  connect(fraLoa.y[1], loa.u)
  connect(fraLoa.y[2], loa1.u)
  connect(setOff.y[1], T2Set.u)
  connect(mode.y[1], con.mode)
  connect(T2Set.y, con.set)
  connect(con.port_b2, loa.port_a)
  connect(loa.port_b, con.port_a2)
  connect(con.port_b2,res2. port_a)
  connect(loa1.port_b, con.port_a2)
  connect(res1.port_b, dp.port_a)
  connect(dp.port_b, del1.ports[2])
  connect(mode.y[1], loa.mode)
  connect(mode.y[1], loa1.mode)
  connect(mode.y[1], isEna.u)
  connect(isEna.y, pum.y1)
end InjectionThreeWay;


Model illustrating the operation of an inversion circuit with two-way valve and check valve and variable secondary. This model is nearly similar to

Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.InjectionTwoWayVariable
except that

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
model InjectionTwoWayCheckValve
  "Model illustrating the operation of an inversion circuit with two-way valve and check valve and variable secondary"
  extends InjectionTwoWayVariable(
    T2Set_nominal=3.2+273.15,
    redeclare ActiveNetworks.InjectionTwoWayCheckValve con(k=0.1, Ti=500));
end InjectionTwoWayCheckValve;


within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
model InjectionTwoWayConstant
  "Model illustrating the operation of an inversion circuit with two-way valve and constant secondary"
  extends
    Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.PartialInjectionTwoWay(
    del2(nPorts=3),
    dp2_nominal=dpPip_nominal + loa1.dpTer_nominal + loa1.dpValve_nominal,
    con(typVar=Buildings.Fluid.HydronicConfigurations.Types.ControlVariable.SupplyTemperature));

  parameter Boolean have_resT2 = false
    "Set to true for consumer circuit temperature reset, false for constant set point"

  parameter Modelica.Units.SI.Temperature T2Set_nominal=
    if con.typVar==Buildings.Fluid.HydronicConfigurations.Types.ControlVariable.SupplyTemperature
    then TLiqEnt_nominal else TLiqLvg_nominal
    "Consumer circuit design temperature set point"
  parameter Modelica.Units.SI.Temperature TAirEnt_nominal=293.15
    "Air entering temperature at design conditions"
  parameter Modelica.Units.SI.MassFraction phiAirEnt_nominal=0.5
    "Air entering relative humidity at design conditions"

  replaceable BaseClasses.LoadThreeWayValveControl loa
    constrainedby BaseClasses.PartialLoadValveControl(
      redeclare final package MediumLiq = MediumLiq,
      final typ=typ,
      final energyDynamics=energyDynamics,
      final mLiq_flow_nominal=mTer_flow_nominal,
      final TAirEnt_nominal=TAirEnt_nominal,
      final phiAirEnt_nominal=phiAirEnt_nominal,
      final TLiqEnt_nominal=TLiqEnt_nominal,
      final TLiqLvg_nominal=TLiqLvg_nominal,
      dpBal1_nominal=dp2_nominal-loa.dpTer_nominal-loa.dpValve_nominal)
    "Load"
  replaceable BaseClasses.LoadThreeWayValveControl loa1
    constrainedby BaseClasses.PartialLoadValveControl(
      redeclare final package MediumLiq = MediumLiq,
      final typ=typ,
      final energyDynamics=energyDynamics,
      final mLiq_flow_nominal=mTer_flow_nominal,
      final TAirEnt_nominal=TAirEnt_nominal,
      final phiAirEnt_nominal=phiAirEnt_nominal,
      final TLiqEnt_nominal=TLiqEnt_nominal,
      final TLiqLvg_nominal=TLiqLvg_nominal,
      dpBal1_nominal=0)
    "Load"
  FixedResistances.PressureDrop res2(
    redeclare final package Medium = MediumLiq,
    m_flow_nominal=con.pum.m_flow_nominal - loa.mLiq_flow_nominal,
    dp_nominal=dpPip_nominal)
    "Pipe pressure drop"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant T2SetLim1(
    final k=T2Set_nominal,
    y(final unit="K", displayUnit="degC"))
    "Consumer circuit temperature design set point "
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable fraLoa(table=[0,0,0; 6,
        0,0; 6.1,1,1; 8,1,1; 9,1,0; 14,0.5,0; 14.5,0,0; 16,0,0; 17,0,1; 21,0,1;
        22,0,0; 24,0,0], timeScale=3600) "Load modulating signal"
  Controls.PIDWithOperatingMode resT2(
    k=1,
    Ti=60,
    reverseActing=false,
    y_reset=1) "PI controller for consumer circuit temperature reset"
  Buildings.Controls.OBC.CDL.Reals.Line T2SetVar(
    y(final unit="K", displayUnit="degC")) if have_resT2
    "Consumer circuit temperature set point (reset)"
  Buildings.Controls.OBC.CDL.Reals.Max yValMax(
    y(final unit="1"))
    "Maximum valve opening"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yValSet(
    k=0.9,
    y(final unit="1"))
    "Valve opening set point"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(
    final k=1,
    y(final unit="1"))
    "One"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(
    final k=0,
    y(final unit="1"))
    "Zero"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant T2SetLim0(
    k=T2Set_nominal + (if con.typCtl == Buildings.Fluid.HydronicConfigurations.Types.Control.Heating
    then -10 else +5), y(final unit="K", displayUnit="degC"))
    "Consumer circuit temperature limiting set point "
  Modelica.Blocks.Routing.RealPassThrough T2SetCst(
   y(final unit="K", displayUnit="degC")) if not have_resT2
    "Consumer circuit temperature set point (constant)"
  Modelica.Blocks.Routing.RealPassThrough T2Set(
    y(final unit="K", displayUnit="degC"))
    "Consumer circuit temperature set point"
equation
  connect(fraLoa.y[1], loa.u)
  connect(fraLoa.y[2], loa1.u)
  connect(con.port_b2, loa.port_a)
  connect(del2.ports[2], loa1.port_b)
  connect(loa.port_b, del2.ports[3])
  connect(con.port_b2, res2.port_a)
  connect(res2.port_b, loa1.port_a)
  connect(resT2.y, T2SetVar.u)
  connect(loa.yVal_actual, yValMax.u2)
  connect(loa1.yVal_actual, yValMax.u1)
  connect(yValMax.y, resT2.u_m)
  connect(mode.y[1], resT2.mode)
  connect(yValSet.y, resT2.u_s)
  connect(zer.y, T2SetVar.x1)
  connect(one.y, T2SetVar.x2)
  connect(T2SetLim1.y, T2SetVar.f2)
  connect(T2SetLim0.y, T2SetVar.f1)
  connect(T2SetLim1.y, T2SetCst.u)
  connect(T2SetCst.y, T2Set.u)
  connect(T2SetVar.y, T2Set.u)
  connect(T2Set.y, con.set)
  connect(mode.y[1], loa.mode)
  connect(mode.y[1], loa1.mode)
end InjectionTwoWayConstant;


Air mass flow rate at design conditions. This model is almost similar to

Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.InjectionTwoWayConstant
except that a cooling system is represented,
and the valve control logic is based on the consumer return temperature.
This model serves mostly as a reference to illustrate the
shortcomings of this control option when used with a variable
consumer circuit such as in

Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.InjectionTwoWayVariableReturn.

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
model InjectionTwoWayConstantReturn
  extends InjectionTwoWayConstant(
    loa(final mAir_flow_nominal=mAir_flow_nominal),
    loa1(final mAir_flow_nominal=mAir_flow_nominal),
    typ=Buildings.Fluid.HydronicConfigurations.Types.Control.Cooling,
    mTer_flow_nominal=2.46,
    TAirEnt_nominal=298.75,
    phiAirEnt_nominal=0.5,
    TLiqEnt_nominal=277.55,
    TLiqLvg_nominal=286.65,
    TLiqSup_nominal=276.15,
    con(typVar=Buildings.Fluid.HydronicConfigurations.Types.ControlVariable.ReturnTemperature));

  parameter Modelica.Units.SI.MassFlowRate mAir_flow_nominal=6.8
    "Air mass flow rate at design conditions"
end InjectionTwoWayConstantReturn;


within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
model InjectionTwoWayVariable
  "Model illustrating the operation of an inversion circuit with two-way valve and variable secondary"
  extends InjectionTwoWayConstantReturn(
    redeclare BaseClasses.LoadTwoWayValveControl loa,
    redeclare BaseClasses.LoadTwoWayValveControl loa1,
    del2(nPorts=4),
    dp2_nominal=dpPip_nominal + dp2Set,
    m2_flow_nominal=2*mTer_flow_nominal/0.9,
    con(
      typPum=Buildings.Fluid.HydronicConfigurations.Types.Pump.VariableInput,
      typVar=Buildings.Fluid.HydronicConfigurations.Types.ControlVariable.SupplyTemperature));

  parameter Modelica.Units.SI.PressureDifference dp2Set(
    final min=0,
    displayUnit="Pa") = loa1.dpTer_nominal + loa1.dpValve_nominal
    "Secondary pressure differential set point"

  Sensors.RelativePressure dp2(redeclare final package Medium = MediumLiq)
    "Differential pressure"
  FixedResistances.PressureDrop resEnd2(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=0.1*m2_flow_nominal,
    final dp_nominal=dp2Set)
    "Pipe pressure drop"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dp2SetVal(
    final k=dp2Set) "Pressure differential set point"
  Controls.PIDWithOperatingMode ctlPum2(
    k=0.1,
    Ti=60,
    r=1e4)     "Pump controller"

equation
  connect(dp2.port_a, loa1.port_a)
  connect(dp2.port_b, loa1.port_b)
  connect(resEnd2.port_b, del2.ports[4])
  connect(dp2SetVal.y, ctlPum2.u_s)
  connect(mode.y[1], ctlPum2.mode)
  connect(dp2.p_rel, ctlPum2.u_m)
  connect(ctlPum2.y, con.yPum)
  connect(res2.port_b, resEnd2.port_a)
end InjectionTwoWayVariable;


within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
model InjectionTwoWayVariableReturn
  "Model illustrating the operation of an inversion circuit with two-way valve and variable secondary with return temperature control"
  extends InjectionTwoWayVariable(
    con(typVar=Buildings.Fluid.HydronicConfigurations.Types.ControlVariable.ReturnTemperature));

  BaseClasses.LoadTwoWayValveControl loaOpe(
    typ=Buildings.Fluid.HydronicConfigurations.Types.Control.Cooling,
    mAir_flow_nominal=mAir_flow_nominal,
    redeclare final package MediumLiq = MediumLiq,
    k=1,
    Ti=1,
    final energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    final mLiq_flow_nominal=mTer_flow_nominal,
    final TAirEnt_nominal=TAirEnt_nominal,
    final phiAirEnt_nominal=phiAirEnt_nominal,
    final TLiqEnt_nominal=TLiqEnt_nominal,
    final TLiqLvg_nominal=TLiqLvg_nominal) "Load with open loop control"
  Buildings.Controls.OBC.CDL.Reals.Sources.Ramp TSupVal1(
    height=6,
    duration=16*3600,
    offset=TLiqEnt_nominal,
    startTime=6*3600,
    y(final unit="K", displayUnit="degC")) "Supply temperature"
  Sources.Boundary_pT refOpe(
    redeclare final package Medium = MediumLiq,
    final p=p_min + 10*(loa1.dpTer_nominal + loa1.dpValve_nominal),
    use_T_in=true,
    nPorts=1) "Pressure and temperature boundary condition"
  Sources.Boundary_pT refOpe1(
    redeclare final package Medium = MediumLiq,
    final p=p_min,
    nPorts=1) "Pressure and temperature boundary condition"
  Sensors.TemperatureTwoPort TSupOpe(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=loa.mLiq_flow_nominal,
    tau=0,
    T_start=loa1.TLiqEnt_nominal) "Supply temperature sensor"
  Sensors.TemperatureTwoPort TRetOpe(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=loa.mLiq_flow_nominal,
    tau=0,
    T_start=loa1.TLiqLvg_nominal) "Return temperature sensor"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant  fraLoa1(k=0.7)
    "Load modulating signal"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant modOpe(
    k=1)
    "Operating mode"
equation
  connect(TSupOpe.port_b, loaOpe.port_a)
  connect(loaOpe.port_b, TRetOpe.port_a)
  connect(TSupVal1.y, refOpe.T_in)
  connect(fraLoa1.y, loaOpe.u)
  connect(refOpe.ports[1], TSupOpe.port_a)
  connect(TRetOpe.port_b, refOpe1.ports[1])
  connect(modOpe.y, loaOpe.mode)
end InjectionTwoWayVariableReturn;


Example models

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks;
package Examples "Example models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
model SingleMixing
  "Model illustrating the operation of single mixing circuits"
  extends BaseClasses.PartialActivePrimary(
    m1_flow_nominal=
      m2_flow_nominal * (TLiqEnt_nominal - TLiqLvg_nominal) / (TLiqSup_nominal - TLiqLvg_nominal),
    dpPum_nominal=10e4,
    del1(nPorts=2),
    pum(typ=Buildings.Fluid.HydronicConfigurations.Types.Pump.NoVariableInput,
        typMod=Buildings.Fluid.HydronicConfigurations.Types.PumpModel.Speed));

  parameter Boolean is_bal=true
    "Set to true for balanced primary branch"

  Buildings.Fluid.HydronicConfigurations.ActiveNetworks.SingleMixing con(
    typPum=Buildings.Fluid.HydronicConfigurations.Types.Pump.NoVariableInput,
    redeclare final package Medium=MediumLiq,
    use_lumFloRes=false,
    final typCtl=typ,
    final energyDynamics=energyDynamics,
    final m2_flow_nominal=m2_flow_nominal,
    final dp1_nominal= dpPum_nominal-dpPip_nominal,
    final dp2_nominal=loa1.dpTer_nominal + loa1.dpValve_nominal + dpPip_nominal,
    final dpBal1_nominal=if is_bal then dpPum_nominal-dpPip_nominal else 0,
    val(fraK=1.0))
    "Hydronic connection"

  Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.LoadThreeWayValveControl
    loa(
    redeclare final package MediumLiq = MediumLiq,
    final typ=typ,
    final energyDynamics=energyDynamics,
    final mLiq_flow_nominal=mTer_flow_nominal,
    final TLiqEnt_nominal=TLiqEnt_nominal,
    final TLiqLvg_nominal=TLiqLvg_nominal)
    "Load"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable fraLoa(table=[0,0,0; 6,
        0,0; 6.1,1,1; 8,1,1; 9,1,0; 14,0.5,0; 14.5,0,0; 16,0,0; 17,0,1; 21,0,1;
        22,0,0; 24,0,0],
      timeScale=3600)
    "Load modulating signal"
  Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.LoadThreeWayValveControl
    loa1(
    redeclare final package MediumLiq = MediumLiq,
    final typ=typ,
    final energyDynamics=energyDynamics,
    final mLiq_flow_nominal=mTer_flow_nominal,
    final TLiqEnt_nominal=TLiqEnt_nominal,
    final TLiqLvg_nominal=TLiqLvg_nominal)
    "Load"
  Sensors.RelativePressure dp(
    redeclare final package Medium = MediumLiq)
    "Differential pressure"
  FixedResistances.PressureDrop res2(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=con.pum.m_flow_nominal - loa.mLiq_flow_nominal,
    final dp_nominal=dpPip_nominal)
    "Pipe pressure drop"
  Buildings.Controls.OBC.CDL.Integers.Sources.TimeTable mode(
    table=[0,0; 6,0; 6,1; 22,1; 22,0; 24,0],
    timeScale=3600,
    period=86400) "Operating mode (time schedule)"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable setOff(table=[0,0; 9,0;
        15,-10; 16,-10; 17,0; 24,0],   timeScale=3600)
    "Offset applied to design supply temperature to compute set point"
  Buildings.Controls.OBC.CDL.Reals.AddParameter T2Set(final p=
        TLiqEnt_nominal, y(final unit="K", displayUnit="degC"))
    "Consumer circuit temperature set point"
  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold isEna(
    final t=Controls.OperatingModes.disabled)
    "Returns true if enabled"
equation
  connect(con.port_b1, dp.port_b)
  connect(con.port_a1, dp.port_a)
  connect(res2.port_b, loa1.port_a)
  connect(fraLoa.y[1], loa.u)
  connect(fraLoa.y[2], loa1.u)
  connect(setOff.y[1], T2Set.u)
  connect(mode.y[1], con.mode)
  connect(T2Set.y, con.set)
  connect(con.port_b2, loa.port_a)
  connect(loa.port_b, con.port_a2)
  connect(loa1.port_b, con.port_a2)
  connect(con.port_b2,res2. port_a)
  connect(res1.port_b, dp.port_a)
  connect(dp.port_b, del1.ports[2])
  connect(mode.y[1], loa.mode)
  connect(mode.y[1], loa1.mode)
  connect(mode.y[1], isEna.u)
  connect(isEna.y, pum.y1)
end SingleMixing;


within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
model ThrottleOpenLoop
  "Model illustrating the operation of throttle circuits with variable speed pump"
  extends BaseClasses.PartialActivePrimary(
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    dpPum_nominal=(dpPip_nominal + dpPip1_nominal + dp1Set)*kSizPum,
    mPum_flow_nominal=m1_flow_nominal / 0.9,
    del1(nPorts=4));

  parameter Boolean is_bal=false
    "Set to true for balanced primary branch"
  parameter Buildings.Fluid.HydronicConfigurations.Types.ValveCharacteristic typCha=
    Buildings.Fluid.HydronicConfigurations.Types.ValveCharacteristic.EqualPercentage
    "Control valve characteristic"

  // Only an approximation: practical authority depends on mass flow rate.
  parameter Modelica.Units.SI.PressureDifference dpValve_nominal(
    final min=0,
    displayUnit="Pa") = dpTer_nominal
    "Control valve pressure drop at design conditions";
  parameter Modelica.Units.SI.PressureDifference dpValve1_nominal(
    final min=0,
    displayUnit="Pa") = dpTer_nominal
    "Control valve pressure drop at design conditions";
  parameter Modelica.Units.SI.PressureDifference dpPip1_nominal(
    displayUnit="Pa") = 3E4
    "Pipe section (between two circuits) pressure drop at design conditions";
  parameter Modelica.Units.SI.PressureDifference dp1Set(displayUnit="Pa")=
    dpValve1_nominal + dpTer_nominal
    "Pressure differential set point"

  Throttle con(
    use_siz=false,
    redeclare final package Medium=MediumLiq,
    final use_lumFloRes=false,
    final energyDynamics=energyDynamics,
    final m2_flow_nominal=mTer_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpBal1_nominal=if is_bal then
      dpPum_nominal - dpPip_nominal - dpTer_nominal - dpValve_nominal
      else 0)
    "Hydronic connection"
  Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.Load
    loa(
    redeclare final package MediumLiq = MediumLiq,
    final typ=typ,
    final dpLiq_nominal=dpTer_nominal,
    final energyDynamics=energyDynamics,
    final mLiq_flow_nominal=mTer_flow_nominal,
    final TLiqEnt_nominal=TLiqEnt_nominal,
    final TLiqLvg_nominal=TLiqLvg_nominal,
    k=10) "Load"
  .Buildings.Controls.OBC.CDL.Reals.Sources.Constant fraLoa(k=1)
    "Load modulating signal"
  Throttle con1(
    use_siz=false,
    final use_lumFloRes=false,
    redeclare final package Medium = MediumLiq,
    final energyDynamics=energyDynamics,
    final m2_flow_nominal=mTer_flow_nominal,
    final dpValve_nominal=dpValve1_nominal,
    final dpBal1_nominal=0)
    "Hydronic connection"
  Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.Load
    loa1(
    redeclare final package MediumLiq = MediumLiq,
    final typ=typ,
    final dpLiq_nominal=dpTer_nominal,
    final energyDynamics=energyDynamics,
    final mLiq_flow_nominal=mTer_flow_nominal,
    final TLiqEnt_nominal=TLiqEnt_nominal,
    final TLiqLvg_nominal=TLiqLvg_nominal,
    k=10) "Load"
  FixedResistances.PressureDrop res1b(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=mPum_flow_nominal - mTer_flow_nominal,
    final dp_nominal=dpPip1_nominal) "Pipe pressure drop"
  Sensors.RelativePressure dp(
    redeclare final package Medium = MediumLiq)
    "Differential pressure"
  Sensors.RelativePressure dp1(
    redeclare final package Medium = MediumLiq)
    "Differential pressure"
  .Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable ope(
    table=[0,1,1; 1,0,1; 2,1,0; 3,0,0],
    extrapolation=Buildings.Controls.OBC.CDL.Types.Extrapolation.HoldLastPoint,
    timeScale=100) "Valve opening signal"
  Buildings.Controls.OBC.CDL.Reals.PID conPID(
    k=1,
    Ti=1,
    r=1e4,
    xi_start=1)
    "Pump controller"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpSetVal(
    final k=dp1Set)
    "Pressure differential set point"
  FixedResistances.PressureDrop resEnd(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=0.1*mPum_flow_nominal,
    final dp_nominal=dp1Set)
    "Pipe pressure drop"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant mode(k=1)
    "Operating mode"
  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold isEna(final t=Controls.OperatingModes.disabled)
    "Returns true if enabled"
equation
  connect(con.port_b2, loa.port_a)
  connect(loa.port_b, con.port_a2)
  connect(fraLoa.y, loa.u)
  connect(con1.port_b2, loa1.port_a)
  connect(con1.port_a2, loa1.port_b)
  connect(fraLoa.y, loa1.u)
  connect(dp1.port_a, res1b.port_b)
  connect(dp1.port_a, con1.port_a1)
  connect(con1.port_b1, dp1.port_b)
  connect(con.port_b1, dp.port_b)
  connect(con.port_a1, dp.port_a)
  connect(ope.y[1], con.yVal)
  connect(ope.y[2], con1.yVal)
  connect(dp1.p_rel, conPID.u_m)
  connect(dpSetVal.y, conPID.u_s)
  connect(res1b.port_b, resEnd.port_a)
  connect(res1.port_b, dp.port_a)
  connect(res1.port_b, res1b.port_a)
  connect(dp.port_b, del1.ports[2])
  connect(del1.ports[3], resEnd.port_b)
  connect(dp1.port_b, del1.ports[4])
  connect(conPID.y, pum.y)
  connect(mode.y, loa.mode)
  connect(mode.y, loa1.mode)
  connect(mode.y, isEna.u)
  connect(isEna.y, pum.y1)
end ThrottleOpenLoop;


Model of a load on a hydronic circuit

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses;
model Load "Model of a load on a hydronic circuit"
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
    redeclare final package Medium=MediumLiq,
    final m_flow_nominal=mLiq_flow_nominal);

  replaceable package MediumAir = Buildings.Media.Air
    "Medium model for air";
  replaceable package MediumLiq = Buildings.Media.Water
    "Medium model for liquid (CHW or HHW)";

  parameter Buildings.Fluid.HydronicConfigurations.Types.Control typ
    "Load type"

  parameter Modelica.Units.SI.MassFlowRate mLiq_flow_nominal = 1
    "Liquid mass flow rate at design conditions";
  parameter Modelica.Units.SI.PressureDifference dpLiq_nominal=0
    "Liquid pressure drop at design conditions";
  parameter Modelica.Units.SI.MassFlowRate mAir_flow_nominal=
    abs(Q_flow_nominal) / 10 / cpAir_nominal
    "Air mass flow rate at design conditions";
  parameter Modelica.Units.SI.Temperature TAirEnt_nominal=
    if typ==Buildings.Fluid.HydronicConfigurations.Types.Control.Heating
      then 20+273.15 else 26+273.15
    "Air entering temperature at design conditions";
  parameter Modelica.Units.SI.Temperature TAirEntChg_nominal=20+273.15
    "Air entering temperature in change-over mode"
  parameter Modelica.Units.SI.MassFraction phiAirEnt_nominal = 0.5
    "Air entering relative humidity at design conditions"
  final parameter Modelica.Units.SI.MassFraction XAirEnt_nominal=
    Buildings.Utilities.Psychrometrics.Functions.X_pTphi(
      MediumAir.p_default, TAirEnt_nominal, phiAirEnt_nominal)
    "Air entering water mass fraction at design conditions (kg/kg air)";
  final parameter Modelica.Units.SI.MassFraction xAirEnt_nominal=
    XAirEnt_nominal / (1 - XAirEnt_nominal)
    "Air entering humidity ratio at design conditions (kg/kg dry air)";
  parameter Modelica.Units.SI.Temperature TLiqEnt_nominal=
    if typ==Buildings.Fluid.HydronicConfigurations.Types.Control.Heating
    then 60+273.15 else 7+273.15
    "Liquid entering temperature at design conditions";
  parameter Modelica.Units.SI.Temperature TLiqLvg_nominal=TLiqEnt_nominal+(
    if typ==Buildings.Fluid.HydronicConfigurations.Types.Control.Heating
    then -10 else +5)
    "Liquid leaving temperature at design conditions";
  parameter Modelica.Units.SI.Temperature TLiqEntChg_nominal=
    60+273.15
    "Liquid entering temperature in change-over mode"

  final parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=
   (MediumLiq.specificEnthalpy_pTX(MediumLiq.p_default, TLiqEnt_nominal, X=MediumLiq.X_default)-
    MediumLiq.specificEnthalpy_pTX(MediumLiq.p_default, TLiqLvg_nominal, X=MediumLiq.X_default))*
    mLiq_flow_nominal
    "Transmitted heat flow rate at design conditions";

  final parameter Modelica.Units.SI.HeatFlowRate QChg_flow_nominal=
    eps_nominal
    * min({mLiq_flow_nominal * cpLiq_nominal, mAir_flow_nominal * cpAirChg_nominal})
    * (TLiqEntChg_nominal - TAirEntChg_nominal)
    "Transmitted heat flow rate in change-over mode";

  final parameter Modelica.Units.SI.Temperature TAirLvgChg_nominal=
    TAirEntChg_nominal + QChg_flow_nominal / cpAirChg_nominal / mAir_flow_nominal
    "Air leaving temperature in change-over mode";

  parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller";
  parameter Real k(
    min=100*Modelica.Constants.eps)=0.1
    "Gain of controller"
  parameter Real Ti(unit="s")=60
    "Time constant of integrator block"

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

  Buildings.Controls.OBC.CDL.Interfaces.RealInput u
    "Load modulating signal"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput mode "Operating mode"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yVal(final unit="1")
    "Valve demand signal"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput u_s(final unit="K",
      displayUnit="degC") "Controller set point"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput u_m(final unit="K",
      displayUnit="degC") "Controller measured value"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dTLiq(final unit="K",
      displayUnit="K") "Liquid deltaT"
  Sources.Boundary_pT outAir(
    redeclare final package Medium = MediumAir,
    nPorts=2)
    "Pressure boundary condition at coil outlet"
  Sensors.TemperatureTwoPort TAirLvg(
    redeclare final package Medium = MediumAir,
    final m_flow_nominal=mAir_flow_nominal,
    T_start=TAirEnt_nominal)
    "Leaving air temperature sensor"
  HeatExchangers.WetCoilEffectivenessNTU coi(
    redeclare final package Medium1 = MediumLiq,
    redeclare final package Medium2 = MediumAir,
    final energyDynamics=energyDynamics,
    final m1_flow_nominal=mLiq_flow_nominal,
    final m2_flow_nominal=mAir_flow_nominal,
    final dp1_nominal=dpLiq_nominal,
    dp2_nominal=0,
    configuration=Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow,
    final use_Q_flow_nominal=true,
    final Q_flow_nominal=Q_flow_nominal,
    final T_a1_nominal=TLiqEnt_nominal,
    final T_a2_nominal=TAirEnt_nominal,
    final w_a2_nominal=xAirEnt_nominal)
    "Coil"
  Sources.MassFlowSource_T souAir(
    redeclare final package Medium = MediumAir,
    final X={XAirEnt_nominal,1 - XAirEnt_nominal},
    final m_flow=mAir_flow_nominal,
    use_T_in=true,
    nPorts=1) "Source for entering air"
  Controls.PIDWithOperatingMode ctl(
    u_s(unit="K", displayUnit="degC"),
    u_m(unit="K", displayUnit="degC"),
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti,
    final reverseActing=typ == Buildings.Fluid.HydronicConfigurations.Types.Control.Heating)
    "Controller for supply air temperature"

  Buildings.Controls.OBC.CDL.Reals.Add  TAirSupSet(
    y(final unit="K", displayUnit="degC"))
    "Compute set point as TAirEnt_nominal + u * (TAirLvg_nominal - TAirEnt_nominal)"
  HeatExchangers.WetCoilEffectivenessNTU coiNom(
    redeclare final package Medium1 = MediumLiq,
    redeclare final package Medium2 = MediumAir,
    final m1_flow_nominal=mLiq_flow_nominal,
    final m2_flow_nominal=mAir_flow_nominal,
    show_T=true,
    dp1_nominal=0,
    dp2_nominal=0,
    configuration=Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow,
    final use_Q_flow_nominal=true,
    final Q_flow_nominal=Q_flow_nominal,
    final T_a1_nominal=TLiqEnt_nominal,
    final T_a2_nominal=TAirEnt_nominal,
    final w_a2_nominal=xAirEnt_nominal,
    final energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitial)
    "Coil operating at design conditions (used for model parameterization)"

  Sources.MassFlowSource_T souAirNom(
    redeclare final package Medium = MediumAir,
    final X={XAirEnt_nominal,1 - XAirEnt_nominal},
    final m_flow=mAir_flow_nominal,
    final T=TAirEnt_nominal,
    nPorts=1)
    "Source for entering air"
  Sources.MassFlowSource_T souLiq(
    redeclare final package Medium = MediumLiq,
    final m_flow=mLiq_flow_nominal,
    final T=TLiqEnt_nominal,
    nPorts=1)
    "Source for entering liquid"
  Sources.Boundary_pT outLiq(
    redeclare final package Medium = MediumLiq,
    nPorts=1)
    "Pressure boundary condition at liquid outlet"
  Sensors.TemperatureTwoPort TLiqEnt(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=mLiq_flow_nominal,
    T_start=TLiqEnt_nominal)
    "Entering liquid temperature sensor"
  Sensors.TemperatureTwoPort TLiqLvg(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=mLiq_flow_nominal,
    T_start=TLiqEnt_nominal)
    "Leaving liquid temperature sensor"
  Buildings.Controls.OBC.CDL.Reals.Subtract dT
    "Compute deltaT"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput Q_flow(
    final unit="W")
    "Total heat flow rate transferred to the load"
  Modelica.Blocks.Sources.RealExpression heaFlo(
    y=coi.Q2_flow)
    "Access coil heat flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yLoa_actual(
    final unit="1")
    "Actual load fraction met"
  Modelica.Blocks.Sources.RealExpression loaFra(
    y=Q_flow/(if mode == Buildings.Fluid.HydronicConfigurations.Controls.OperatingModes.heating
      then QChg_flow_nominal else coiNom.Q2_flow))
    "Compute actual load fraction"
  Sensors.TemperatureTwoPort TAirLvgNom(
    redeclare final package Medium = MediumAir,
    final m_flow_nominal=mAir_flow_nominal,
    T_start=TAirEnt_nominal)
    "Leaving air temperature sensor"
  Buildings.Controls.OBC.CDL.Reals.Subtract sub
    "Compute TAirLvg_nominal - TAirEnt_nominal"
  Buildings.Controls.OBC.CDL.Reals.Multiply pro
    "Compute u * (TAirLvg_nominal - TAirEnt_nominal)"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TAirEntVal[3](final k=
        {TAirEnt_nominal,TAirEnt_nominal,TAirEntChg_nominal})
    "Values of entering air temperature"
  Buildings.Controls.OBC.CDL.Routing.RealExtractor TAirEnt_actual(
    y(final unit="K", displayUnit="degC"), final nin=3)
    "Actual value of entering air temperature"
  Buildings.Controls.OBC.CDL.Routing.RealExtractor TAirLvg_actual(
    y(final unit="K", displayUnit="degC"), final nin=3)
    "Actual value of leaving air temperature"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TAirLvgVal(
    final k=TAirLvgChg_nominal) "Values of leaving air temperature"

  Buildings.Controls.OBC.CDL.Integers.AddParameter addPar(final p=1)
    "Convert mode index to array index"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaScaRep(nout=2)
    "Replicate"
protected
  final parameter Modelica.Units.SI.SpecificHeatCapacity cpLiq_nominal=
    MediumLiq.specificHeatCapacityCp(MediumLiq.setState_pTX(
      p=MediumLiq.p_default,
      T=TLiqEnt_nominal))
    "Liquid specific heat capacity at design conditions";
  final parameter Modelica.Units.SI.SpecificHeatCapacity cpAir_nominal=
    MediumAir.specificHeatCapacityCp(MediumAir.setState_pTX(
      p=MediumAir.p_default,
      T=TLiqEnt_nominal,
      X={XAirEnt_nominal,1 - XAirEnt_nominal}))
    "Air specific heat capacity at design conditions";
  final parameter Modelica.Units.SI.SpecificHeatCapacity cpAirChg_nominal=
    MediumAir.specificHeatCapacityCp(MediumAir.setState_pTX(
      p=MediumAir.p_default,
      T=TLiqEntChg_nominal,
      X={XAirEnt_nominal,1 - XAirEnt_nominal}))
    "Air specific heat capacity in change-over mode";
   parameter Real eps_nominal=
     Buildings.Fluid.HeatExchangers.BaseClasses.epsilon_C(
       UA=coiNom.UA_nominal,
       C1_flow=mLiq_flow_nominal * cpLiq_nominal,
       C2_flow=mAir_flow_nominal * cpAir_nominal,
       flowRegime=Integer(Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow),
       CMin_flow_nominal=min({mLiq_flow_nominal * cpLiq_nominal, mAir_flow_nominal * cpAir_nominal}),
       CMax_flow_nominal=max({mLiq_flow_nominal * cpLiq_nominal, mAir_flow_nominal * cpAir_nominal}));

initial equation
  assert(typ<>Buildings.Fluid.HydronicConfigurations.Types.Control.None,
    "In " + getInstanceName() +
    ": The type of built-in controls cannot be None: select any other valid option.");
equation
  connect(souAir.ports[1], coi.port_a2)
  connect(outAir.ports[1],TAirLvg. port_b)
  connect(TAirLvg.port_a, coi.port_b2)
  connect(ctl.y, yVal)
  connect(TAirSupSet.y, ctl.u_s)
  connect(souAirNom.ports[1], coiNom.port_a2)
  connect(souLiq.ports[1], coiNom.port_a1)
  connect(coiNom.port_b1, outLiq.ports[1])
  connect(TAirSupSet.y, u_s)
  connect(port_a, TLiqEnt.port_a)
  connect(TLiqEnt.port_b, coi.port_a1)
  connect(coi.port_b1, TLiqLvg.port_a)
  connect(TLiqLvg.port_b, port_b)
  connect(dT.y, dTLiq)
  connect(TLiqLvg.T, dT.u1)
  connect(TLiqEnt.T, dT.u2)
  connect(TAirLvg.T, ctl.u_m)
  connect(TAirLvg.T, u_m)
  connect(heaFlo.y, Q_flow)
  connect(yLoa_actual, loaFra.y)
  connect(coiNom.port_b2, TAirLvgNom.port_a)
  connect(TAirLvgNom.port_b, outAir.ports[2])
  connect(mode, ctl.mode)
  connect(TAirEntVal.y, TAirEnt_actual.u)
  connect(pro.y, TAirSupSet.u2)
  connect(TAirEnt_actual.y, TAirSupSet.u1)
  connect(sub.y, pro.u1)
  connect(u, pro.u2)
  connect(TAirEnt_actual.y, souAir.T_in)
  connect(sub.u1, TAirLvg_actual.y)
  connect(TAirEnt_actual.y, sub.u2)
  connect(addPar.y, TAirEnt_actual.index)
  connect(addPar.y, TAirLvg_actual.index)
  connect(mode, addPar.u)
  connect(TAirLvgNom.T, reaScaRep.u)
  connect(reaScaRep.y, TAirLvg_actual.u[1:2])
  connect(TAirLvgVal.y, TAirLvg_actual.u[3])
end Load;


Model of a load on hydronic circuit with flow rate modulation by three-way valve. This is a model of a thermal load on a hydronic circuit that
is composed of

Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.Load
and a diversion circuit with a three-way valve
that is used to modulate the flow rate through the load component.

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses;
model LoadThreeWayValveControl
  "Model of a load on hydronic circuit with flow rate modulation by three-way valve"
  extends PartialLoadValveControl(
    redeclare HydronicConfigurations.ActiveNetworks.Diversion con);
end LoadThreeWayValveControl;


Model of a load on hydronic circuit with flow rate modulation by two-way valve. This is a model of a thermal load on a hydronic circuit that
is composed of

Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.Load
and a throttle circuit with a two-way valve
that is used to modulate the flow rate through the load component.

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses;
model LoadTwoWayValveControl
  "Model of a load on hydronic circuit with flow rate modulation by two-way valve"
  extends PartialLoadValveControl(
    redeclare HydronicConfigurations.ActiveNetworks.Throttle con);
end LoadTwoWayValveControl;


Package with base classes

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples;
package BaseClasses "Package with base classes"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial model of active primary network

within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses;
partial model PartialActivePrimary
  "Partial model of active primary network"
  extends Modelica.Icons.Example;

  package MediumLiq = Buildings.Media.Water
    "Medium model for hot water";

  parameter Buildings.Fluid.HydronicConfigurations.Types.Control
    typ=Buildings.Fluid.HydronicConfigurations.Types.Control.Heating
    "Load type"

  parameter Integer nTer=2
    "Number of terminal units";
  parameter Modelica.Units.SI.MassFlowRate mTer_flow_nominal = 1
    "Terminal unit mass flow rate at design conditions"
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal(final min=0)=
    m2_flow_nominal
    "Mass flow rate in primary branch at design conditions"
  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal(final min=0)=
    nTer * mTer_flow_nominal
    "Mass flow rate in consumer circuit at design conditions"
  parameter Modelica.Units.SI.PressureDifference dpTer_nominal(displayUnit="Pa")=
    3E4
    "Terminal unit pressure drop at design conditions"
  parameter Modelica.Units.SI.PressureDifference dpPip_nominal(displayUnit="Pa")=
     0.5E4
    "Pipe section pressure drop at design conditions"
  parameter Real kSizPum(unit="1")=1.0
    "Pump oversizing coefficient";
  parameter Modelica.Units.SI.PressureDifference dpPum_nominal(
    final min=0,
    displayUnit="Pa")
    "Pump head at design conditions"
  parameter Modelica.Units.SI.MassFlowRate mPum_flow_nominal=m1_flow_nominal
    "Primary pump mass flow rate at design conditions"

  parameter Modelica.Units.SI.Pressure p_min=200000
    "Circuit minimum pressure";

  parameter Modelica.Units.SI.Temperature TLiqEnt_nominal=
    if typ==Buildings.Fluid.HydronicConfigurations.Types.Control.Heating
    then 60+273.15 else 7+273.15
    "Liquid entering temperature at design conditions";
  parameter Modelica.Units.SI.Temperature TLiqLvg_nominal=TLiqEnt_nominal+(
    if typ==Buildings.Fluid.HydronicConfigurations.Types.Control.Heating
    then -10 else +5)
    "Liquid leaving temperature at design conditions";
  parameter Modelica.Units.SI.Temperature TLiqEntChg_nominal=
    60+273.15
    "Liquid entering temperature in change-over mode"

  parameter Modelica.Units.SI.Temperature TLiqSup_nominal=TLiqEnt_nominal
    "Liquid primary supply temperature at design conditions";
  parameter Modelica.Units.SI.Temperature TLiqSupChg_nominal=TLiqEntChg_nominal
    "Liquid primary supply temperature in change-over mode"

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

  Sources.Boundary_pT ref(
    redeclare final package Medium = MediumLiq,
    final p=p_min,
    final T=TLiqSup_nominal,
    nPorts=2)
    "Pressure and temperature boundary condition"
  Buildings.Fluid.HydronicConfigurations.Components.Pump pum(
    redeclare final package Medium = MediumLiq,
    final energyDynamics=energyDynamics,
    addPowerToMedium=false,
    use_riseTime=energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState,
    final m_flow_nominal=mPum_flow_nominal,
    final dp_nominal=dpPum_nominal) "Circulation pump"

  FixedResistances.PressureDrop res1(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=mPum_flow_nominal,
    final dp_nominal=dpPip_nominal) "Pipe pressure drop"
  Sensors.TemperatureTwoPort T1Ret(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=mPum_flow_nominal,
    final tau=if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState
         then 0 else 1,
    T_start=TLiqSup_nominal) "Return temperature sensor"
  Sensors.TemperatureTwoPort T1Sup(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=mPum_flow_nominal,
    final tau=if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState
         then 0 else 1,
    T_start=TLiqSup_nominal) "Supply temperature sensor"
  Buildings.Controls.OBC.CDL.Reals.Subtract dT1(y(final unit="K"))
    "Primary Delta-T"
  Delays.DelayFirstOrder del1(
    redeclare final package Medium = MediumLiq,
    final energyDynamics=energyDynamics,
    final m_flow_nominal=mPum_flow_nominal,
    nPorts=1)
    "Fluid transport delay"
equation
  connect(pum.port_b, T1Sup.port_a)
  connect(T1Sup.port_b, res1.port_a)
  connect(T1Ret.T, dT1.u1)
  connect(T1Sup.T, dT1.u2)

  connect(ref.ports[1], pum.port_a)
  connect(ref.ports[2], T1Ret.port_b)
  connect(T1Ret.port_a, del1.ports[1])
end PartialActivePrimary;


within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses;
partial model PartialDecoupling
  "Partial model of primary variable circuit serving a decoupling circuit"
  extends BaseClasses.PartialActivePrimary(
    typ=Buildings.Fluid.HydronicConfigurations.Types.Control.ChangeOver,
    m2_flow_nominal=nTer*mTer_flow_nominal/0.9,
    m1_flow_nominal=1.1*m2_flow_nominal,
    mPum_flow_nominal=m1_flow_nominal/0.9,
    dpPum_nominal=10e4,
    del1(nPorts=3),
    pum(typ=Buildings.Fluid.HydronicConfigurations.Types.Pump.NoVariableInput,
        typMod=Buildings.Fluid.HydronicConfigurations.Types.PumpModel.Head),
    ref(use_T_in=true));

  parameter Boolean is_bal=true
    "Set to true for balanced primary branch"

  parameter Modelica.Units.SI.PressureDifference dp2Set(displayUnit="Pa")=
    loa1.dpTer_nominal + loa1.dpValve_nominal
    "Consumer circuit pressure differential set point"

  parameter Modelica.Units.SI.PressureDifference dp2_nominal(displayUnit="Pa")=
    dpPip_nominal + dp2Set
    "Consumer circuit pressure differential at design conditions"

  parameter Modelica.Units.SI.PressureDifference dp1_nominal(displayUnit="Pa")=
    dpPum_nominal - dpPip_nominal
    "Control valve pressure drop at design conditions";

  Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Decoupling con(
    typPum=Buildings.Fluid.HydronicConfigurations.Types.Pump.VariableInput,
    typCtl=typ,
    redeclare final package Medium=MediumLiq,
    final energyDynamics=energyDynamics,
    final m1_flow_nominal=m1_flow_nominal,
    final m2_flow_nominal=m2_flow_nominal,
    final dp1_nominal=dp1_nominal,
    final dp2_nominal=dp2_nominal,
    final dpBal1_nominal=if is_bal then
      dpPum_nominal-dpPip_nominal-con.dpValve_nominal-con.dpBal3_nominal else 0)
    "Hydronic connection"

  Sensors.RelativePressure dp(
    redeclare final package Medium = MediumLiq)
    "Differential pressure"
  BaseClasses.LoadTwoWayValveControl loa(
    redeclare final package MediumLiq = MediumLiq,
    final typ=typ,
    final energyDynamics=energyDynamics,
    final mLiq_flow_nominal=mTer_flow_nominal,
    final TLiqEnt_nominal=TLiqEnt_nominal,
    final TLiqEntChg_nominal=TLiqEntChg_nominal,
    final TLiqLvg_nominal=TLiqLvg_nominal,
    dpBal1_nominal=dp2_nominal - loa.dpTer_nominal - loa.dpValve_nominal)
    "Load"
  BaseClasses.LoadTwoWayValveControl loa1(
    redeclare final package MediumLiq = MediumLiq,
    final typ=typ,
    final energyDynamics=energyDynamics,
    final mLiq_flow_nominal=mTer_flow_nominal,
    final TLiqEnt_nominal=TLiqEnt_nominal,
    final TLiqEntChg_nominal=TLiqEntChg_nominal,
    final TLiqLvg_nominal=TLiqLvg_nominal,
    dpBal1_nominal=0)
    "Load"
  FixedResistances.PressureDrop res2(
    redeclare final package Medium = MediumLiq,
    m_flow_nominal=con.pum.m_flow_nominal - loa.mLiq_flow_nominal,
    dp_nominal=dpPip_nominal)
    "Pipe pressure drop"
  Sensors.RelativePressure dp2(redeclare final package Medium = MediumLiq)
    "Differential pressure"
  FixedResistances.PressureDrop resEnd2(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=0.1*m2_flow_nominal,
    final dp_nominal=dp2Set)
    "Pipe pressure drop"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dp2SetVal(final k=
        dp2Set) "Pressure differential set point"
  Buildings.Controls.OBC.CDL.Reals.PIDWithReset ctlPum2(
    k=0.1,
    Ti=60,
    r=1e4,
    y_reset=0) "Secondary pump controller"
  FixedResistances.PressureDrop resEnd1(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=0.1*mPum_flow_nominal,
    final dp_nominal=dpPum_nominal)
    "Pipe pressure drop"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable fraLoa(table=[0,0,0; 6,
        0,0; 6.1,1,1; 8,1,1; 9,1,0; 14,0.5,0; 14.5,0,0; 16,0,0; 17,0,1; 21,0,1;
        22,0,0; 24,0,0], timeScale=3600) "Load modulating signal"
  Delays.DelayFirstOrder del2(
    redeclare final package Medium = MediumLiq,
    final energyDynamics=energyDynamics,
    final m_flow_nominal=m2_flow_nominal,
    nPorts=3) "Fluid transport delay"
  Buildings.Controls.OBC.CDL.Integers.Sources.TimeTable mode(
    table=[0,0; 6,0; 6,2; 13,2; 13,1; 22,1; 22,0; 24,0],
    timeScale=3600,
    period=86400) "Operating mode (time schedule)"
  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold isEna(final t=Controls.OperatingModes.disabled)
    "Returns true if enabled"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant T1SetVal[3](final k={
        MediumLiq.T_default,TLiqSup_nominal,TLiqSupChg_nominal})
    "Primary circuit temperature set point values"
  Buildings.Controls.OBC.CDL.Routing.RealExtractor T1Set(nin=3,
    y(final unit="K", displayUnit="degC"))
    "Primary circuit temperature set point"
  Sensors.TemperatureTwoPort T1ConRet(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=con.m2_flow_nominal,
    tau=if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState then 0
         else 1) "Primary branch return temperature sensor"
  FixedResistances.Junction jun(
    redeclare final package Medium=MediumLiq,
    final energyDynamics=energyDynamics,
    final m_flow_nominal=m2_flow_nominal .* {1,-1,-1},
    final dp_nominal=fill(0, 3))
    "Junction"
  Buildings.Controls.OBC.CDL.Integers.AddParameter addPar(final p=1)
    "Convert mode index to array index"
equation
  connect(con.port_a1, dp.port_a)
  connect(res1.port_b, dp.port_a)
  connect(dp.port_b, del1.ports[2])
  connect(fraLoa.y[1],loa. u)
  connect(fraLoa.y[2],loa1. u)
  connect(mode.y[1],loa. mode)
  connect(mode.y[1],loa1. mode)
  connect(dp2.p_rel, ctlPum2.u_m)
  connect(res1.port_b, resEnd1.port_a)
  connect(resEnd1.port_b, del1.ports[3])
  connect(dp2SetVal.y, ctlPum2.u_s)
  connect(mode.y[1], con.mode)
  connect(mode.y[1], isEna.u)
  connect(T1Set.y, ref.T_in)
  connect(T1SetVal.y, T1Set.u)
  connect(con.port_b1, T1ConRet.port_a)
  connect(T1ConRet.port_b, dp.port_b)

  connect(ctlPum2.y, con.yPum)
  connect(isEna.y, pum.y1)
  connect(jun.port_3, loa.port_a)
  connect(jun.port_2, res2.port_a)
  connect(res2.port_b, loa1.port_a)
  connect(loa1.port_b, del2.ports[1])
  connect(res2.port_b, resEnd2.port_a)
  connect(resEnd2.port_b, del2.ports[2])
  connect(loa.port_b, del2.ports[3])
  connect(loa1.port_a, dp2.port_a)
  connect(loa1.port_b, dp2.port_b)
  connect(isEna.y, ctlPum2.trigger)
  connect(addPar.y, T1Set.index)
  connect(mode.y[1], addPar.u)
end PartialDecoupling;


within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses;
partial model PartialInjectionTwoWay
  "Partial model of primary variable circuit serving an inversion circuit with two-way valve"
  extends PartialActivePrimary(
    TLiqEnt_nominal=55+273.15,
    TLiqSup_nominal=60+273.15,
    dpPum_nominal=(dpPip_nominal + dp1Set) * kSizPum,
    m1_flow_nominal=m2_flow_nominal * (TLiqEnt_nominal - TLiqLvg_nominal) /
      (TLiqSup_nominal - TLiqLvg_nominal),
    mPum_flow_nominal=m1_flow_nominal / 0.9,
    del1(nPorts=3));

  parameter Boolean is_bal=false
    "Set to true for balanced primary branch"

  parameter Modelica.Units.SI.PressureDifference dp1Set(displayUnit="Pa")=1e4
    "Pressure differential set point"
  parameter Modelica.Units.SI.PressureDifference dp2_nominal(displayUnit="Pa")
    "Consumer circuit pressure differential at design conditions"

  Sensors.RelativePressure dp1(
    redeclare final package Medium = MediumLiq)
    "Differential pressure"
  Buildings.Controls.OBC.CDL.Integers.Sources.TimeTable mode(
    table=[0,0; 6,0; 6,1; 22,1; 22,0; 24,0],
    timeScale=3600,
    period=86400) "Operating mode (time schedule)"

  replaceable InjectionTwoWay con(
    use_lumFloRes=true,
    typCtl=typ,
    typPum=Buildings.Fluid.HydronicConfigurations.Types.Pump.NoVariableInput,
    redeclare final package Medium = MediumLiq,
    final energyDynamics=energyDynamics,
    final m1_flow_nominal=m1_flow_nominal,
    final m2_flow_nominal=m2_flow_nominal,
    final dp1_nominal=dp1Set,
    final dp2_nominal=dp2_nominal,
    final dpBal1_nominal=if is_bal then dp1Set - con.dpValve_nominal else 0,
    pum(addPowerToMedium=false))
    "Hydronic connection"

  FixedResistances.PressureDrop resEnd1(
    redeclare final package Medium = MediumLiq,
    final m_flow_nominal=0.1*mPum_flow_nominal,
    final dp_nominal=dp1Set)
    "Pipe pressure drop"
  Buildings.Controls.OBC.CDL.Reals.PIDWithReset ctlPum1(
    k=0.1,
    Ti=60,
    r=1e4,
    y_reset=0) "Primary pump controller"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dp1SetVal(final k=
        dp1Set) "Pressure differential set point"

  Delays.DelayFirstOrder del2(
    redeclare final package Medium = MediumLiq,
    final energyDynamics=energyDynamics,
    final m_flow_nominal=m2_flow_nominal,
    nPorts=1) "Fluid transport delay"

  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold isEna(final t=Controls.OperatingModes.disabled)
    "Returns true if enabled"
equation
  connect(con.port_b1, dp1.port_b)
  connect(con.port_a1, dp1.port_a)
  connect(dp1SetVal.y, ctlPum1.u_s)
  connect(dp1.p_rel, ctlPum1.u_m)
  connect(mode.y[1], con.mode)
  connect(del2.ports[1], con.port_a2)

  connect(res1.port_b, dp1.port_a)
  connect(res1.port_b, resEnd1.port_a)
  connect(dp1.port_b, del1.ports[2])
  connect(resEnd1.port_b, del1.ports[3])
  connect(ctlPum1.y, pum.y)
  connect(isEna.y, pum.y1)
  connect(mode.y[1], isEna.u)
  connect(isEna.y, ctlPum1.trigger)
end PartialInjectionTwoWay;


within Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses;
partial model PartialLoadValveControl
  "Partial model of a load on hydronic circuit with flow rate modulation by control valve"
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
    redeclare final package Medium=MediumLiq,
    final m_flow_nominal=mLiq_flow_nominal);

  replaceable package MediumAir = Buildings.Media.Air
    "Medium model for air";
  replaceable package MediumLiq = Buildings.Media.Water
    "Medium model for liquid (CHW or HHW)";

  parameter Buildings.Fluid.HydronicConfigurations.Types.Control typ
    "Load type"

  parameter Modelica.Units.SI.MassFlowRate mLiq_flow_nominal = 1
    "Liquid mass flow rate at design conditions";

  parameter Modelica.Units.SI.PressureDifference dpTer_nominal(
    displayUnit="Pa")=3E4
    "Liquid pressure drop across terminal unit at design conditions";
  parameter Modelica.Units.SI.PressureDifference dpValve_nominal(
    displayUnit="Pa")=dpTer_nominal
    "Control valve pressure drop at design conditions"
  parameter Modelica.Units.SI.PressureDifference dpBal1_nominal(
    displayUnit="Pa")=0
    "Balancing valve pressure drop at design conditions"

  parameter Modelica.Units.SI.MassFlowRate mAir_flow_nominal=
    abs(Q_flow_nominal) / 10 / 1015
    "Air mass flow rate at design conditions";
  parameter Modelica.Units.SI.Temperature TAirEnt_nominal=
    if typ==Buildings.Fluid.HydronicConfigurations.Types.Control.Heating
      then 20+273.15 else 26+273.15
    "Air entering temperature at design conditions";
  parameter Modelica.Units.SI.Temperature TAirEntChg_nominal=20+273.15
    "Air entering temperature in change-over mode"
  parameter Modelica.Units.SI.MassFraction phiAirEnt_nominal = 0.5
    "Air entering relative humidity at design conditions"
  parameter Modelica.Units.SI.Temperature TLiqEnt_nominal=
    if typ==Buildings.Fluid.HydronicConfigurations.Types.Control.Heating
      then 60+273.15 else 7+273.15
    "Liquid entering temperature at design conditions";
  parameter Modelica.Units.SI.Temperature TLiqLvg_nominal=TLiqEnt_nominal+(
    if typ==Buildings.Fluid.HydronicConfigurations.Types.Control.Heating
      then -10 else +5)
    "Liquid leaving temperature at design conditions";
  parameter Modelica.Units.SI.Temperature TLiqEntChg_nominal=
    60+273.15
    "Liquid entering temperature in change-over mode"

  final parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=
   (MediumLiq.specificEnthalpy_pTX(MediumLiq.p_default, TLiqEnt_nominal, X=MediumLiq.X_default)-
    MediumLiq.specificEnthalpy_pTX(MediumLiq.p_default, TLiqLvg_nominal, X=MediumLiq.X_default))*
    mLiq_flow_nominal
    "Transmitted heat flow rate at design conditions"

  parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType=
    Buildings.Controls.OBC.CDL.Types.SimpleController.PI
    "Type of controller";
  parameter Real k(
    min=100*Modelica.Constants.eps)=0.1
    "Gain of controller"
  parameter Real Ti(unit="s")=60
    "Time constant of integrator block"

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

  Buildings.Controls.OBC.CDL.Interfaces.RealInput u
    "Load modulating signal"
  Buildings.Controls.OBC.CDL.Interfaces.IntegerInput mode "Operating mode"

  Buildings.Fluid.HydronicConfigurations.ActiveNetworks.Examples.BaseClasses.Load
    loa(
    redeclare final package MediumAir = MediumAir,
    redeclare final package MediumLiq = MediumLiq,
    final typ=typ,
    final mLiq_flow_nominal=mLiq_flow_nominal,
    final dpLiq_nominal=0,
    final mAir_flow_nominal=mAir_flow_nominal,
    final TAirEnt_nominal=TAirEnt_nominal,
    final phiAirEnt_nominal=phiAirEnt_nominal,
    final TLiqEnt_nominal=TLiqEnt_nominal,
    final TLiqLvg_nominal=TLiqLvg_nominal,
    final TAirEntChg_nominal=TAirEntChg_nominal,
    final TLiqEntChg_nominal=TLiqEntChg_nominal,
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti,
    final energyDynamics=energyDynamics) "Load"
  replaceable HydronicConfigurations.Interfaces.PartialHydronicConfiguration con
    constrainedby
    HydronicConfigurations.Interfaces.PartialHydronicConfiguration(
    redeclare final package Medium=MediumLiq,
    final use_siz=false,
    final dp2_nominal=dpTer_nominal,
    final m2_flow_nominal=m_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpBal1_nominal=dpBal1_nominal,
    use_lumFloRes=true,
    final energyDynamics=energyDynamics)
    "Diversion connection"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yLoa_actual(final unit="1")
    "Actual load fraction met"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput Q_flow(final unit="W")
    "Total heat flow rate transferred to the load"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput yVal_actual(final unit="1")
    "Valve position feedback"
equation
  connect(port_a, con.port_a1)
  connect(con.port_b1, port_b)
  connect(con.port_b2, loa.port_a)
  connect(con.port_a2, loa.port_b)
  connect(loa.yVal, con.yVal)
  connect(u, loa.u)
  connect(loa.yLoa_actual, yLoa_actual)
  connect(loa.Q_flow, Q_flow)
  connect(con.yVal_actual, yVal_actual)
  connect(mode, loa.mode)
  connect(mode, con.mode)
end PartialLoadValveControl;


Package with base classes

within Buildings.Fluid.HydronicConfigurations;
package BaseClasses "Package with base classes"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Single mixing circuit

within Buildings.Fluid.HydronicConfigurations.BaseClasses;
model SingleMixing "Single mixing circuit"
  extends Fluid.HydronicConfigurations.Interfaces.PartialHydronicConfiguration(
    set(final unit="K", displayUnit="degC"),
    dpValve_nominal=max(dp1_nominal, 3E3),
    dpPum_nominal=dp2_nominal + dpBal2_nominal +
      max({val.dpValve_nominal, val.dp3Valve_nominal + dpBal3_nominal}),
    final m1_flow_nominal=m2_flow_nominal,
    final typVal=Buildings.Fluid.HydronicConfigurations.Types.Valve.ThreeWay,
    final use_dp1=use_siz,
    final use_dp2=use_siz and typPum<>Buildings.Fluid.HydronicConfigurations.Types.Pump.None,
    final have_typVar=false);

  Buildings.Fluid.HydronicConfigurations.Components.ThreeWayValve val(
    redeclare final package Medium=Medium,
    final typCha=typCha,
    final energyDynamics=energyDynamics,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    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 m_flow_nominal=m2_flow_nominal,
    final dpValve_nominal=dpValve_nominal,
    final dpFixed_nominal=if use_lumFloRes then {dpBal1_nominal, dpBal3_nominal} else {0,0},
    final flowCharacteristics1=flowCharacteristics1,
    final flowCharacteristics3=flowCharacteristics3)
    "Control valve"
  FixedResistances.Junction jun(
    redeclare final package Medium = Medium,
    final energyDynamics=energyDynamics,
    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,
    final m_flow_nominal=m1_flow_nominal .* {1,-1,-1},
    final dp_nominal=fill(0, 3))
    "Junction"
  FixedResistances.PressureDrop res1(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m1_flow_nominal,
    final dp_nominal=if use_lumFloRes then 0 else dpBal1_nominal)
    "Primary balancing valve"
  FixedResistances.PressureDrop res2(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m2_flow_nominal,
    final dp_nominal=dpBal2_nominal)
    "Secondary balancing valve"
  Buildings.Fluid.HydronicConfigurations.Components.Pump pum(
    redeclare final package Medium = Medium,
    final typ=typPum,
    final typMod=typPumMod,
    final m_flow_nominal=mPum_flow_nominal,
    final dp_nominal=dpPum_nominal,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    use_riseTime=energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState,
    final per=perPum) "Pump"
  Sensors.TemperatureTwoPort T2Sup(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m2_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    tau=if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState then 0
         else 1) "Consumer circuit supply temperature sensor"
  Controls.PIDWithOperatingMode ctl(
    u_s(final unit="K", displayUnit="degC"),
    u_m(final unit="K", displayUnit="degC"),
    final reverseActing=typCtl == Buildings.Fluid.HydronicConfigurations.Types.Control.Heating,
    final yMin=0,
    final yMax=1,
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti)
    if typCtl <> Buildings.Fluid.HydronicConfigurations.Types.Control.None
    "Controller"

  Buildings.Controls.OBC.CDL.Integers.GreaterThreshold isEna(
    final t=Controls.OperatingModes.disabled)
    "Returns true if enabled"
  Sensors.TemperatureTwoPort T2Ret(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m2_flow_nominal,
    final allowFlowReversal=allowFlowReversal,
    tau=if energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState then 0
         else 1) "Consumer circuit return temperature sensor"
  FixedResistances.PressureDrop res3(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m2_flow_nominal,
    final dp_nominal=if use_lumFloRes then 0 else dpBal3_nominal)
    "Bypass balancing valve"
equation
  connect(port_b1,res1. port_b)
  connect(pum.port_b, T2Sup.port_a)
  connect(T2Sup.port_b, port_b2)
  connect(ctl.y, val.y)
  connect(mode, ctl.mode)
  connect(T2Sup.T, ctl.u_m)
  connect(set, ctl.u_s)
  connect(yVal, val.y)
  connect(mode, isEna.u)
  connect(jun.port_2,res1. port_a)
  connect(res2.port_b, jun.port_1)
  connect(val.port_2, pum.port_a)
  connect(val.port_1, port_a1)
  connect(pum.P, PPum)
  connect(pum.y_actual, yPum_actual)
  connect(port_a2, T2Ret.port_a)
  connect(T2Ret.port_b,res2. port_a)
  connect(jun.port_3, res3.port_a)
  connect(res3.port_b, val.port_3)
  connect(val.y_actual, yVal_actual)
  connect(isEna.y, pum.y1)
  connect(yPum, pum.y)
end SingleMixing;


Package with component models

within Buildings.Fluid.HydronicConfigurations;
package Components "Package with component models"
  extends Modelica.Icons.VariantsPackage;
end Components;


Container class for circulating pumps

within Buildings.Fluid.HydronicConfigurations.Components;
model Pump "Container class for circulating pumps"
  extends Buildings.Fluid.Interfaces.LumpedVolumeDeclarations(
    final massDynamics=energyDynamics,
    final mSenFac=1);
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
    m_flow_nominal(
      final min=Modelica.Constants.small),
    show_T=false,
    port_a(
      h_outflow(start=h_outflow_start)),
    port_b(
      h_outflow(start=h_outflow_start),
      p(start=p_start),
      final m_flow(max = if allowFlowReversal then +Modelica.Constants.inf else 0)));

  parameter Buildings.Fluid.HydronicConfigurations.Types.Pump typ=
    Buildings.Fluid.HydronicConfigurations.Types.Pump.VariableInput
    "Type of secondary pump"

  parameter Buildings.Fluid.HydronicConfigurations.Types.PumpModel typMod=
    Buildings.Fluid.HydronicConfigurations.Types.PumpModel.Speed
    "Type of pump model"

  parameter Modelica.Units.SI.PressureDifference dp_nominal(displayUnit="Pa")
    "Pump head at design conditions"

  replaceable parameter Buildings.Fluid.Movers.Data.Generic per
    constrainedby Buildings.Fluid.Movers.Data.Generic(
      pressure(
        V_flow={0, 1, 2} * m_flow_nominal / rho_default,
        dp={1.14, 1, 0.42} * dp_nominal))
    "Record with performance data"

  parameter Buildings.Fluid.Types.InputType inputType=
    Buildings.Fluid.Types.InputType.Continuous
    "Control input type"

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

  // Classes used to implement the filtered speed
  parameter Boolean use_riseTime=true
    "Set to true to continuously change motor speed"
  parameter Modelica.Units.SI.Time riseTime=30
    "Time needed to change motor speed between zero and full speed"
  parameter Modelica.Blocks.Types.Init init=Modelica.Blocks.Types.Init.InitialOutput
    "Type of initialization (no init/steady state/initial state/initial output)"

  // Variables
  Modelica.Units.SI.VolumeFlowRate VMachine_flow = V_flow.V_flow
    "Volume flow rate";
  Modelica.Units.SI.PressureDifference dpMachine(displayUnit="Pa") = port_b.p - port_a.p
    "Pressure rise";

  Buildings.Controls.OBC.CDL.Interfaces.RealInput y(
    final unit="1")
    if typ==Buildings.Fluid.HydronicConfigurations.Types.Pump.VariableInput
    "Analog control signal"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput y1
    if typ<>Buildings.Fluid.HydronicConfigurations.Types.Pump.None
    "Start signal"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput y_actual(
    final unit="1") if typ<>Buildings.Fluid.HydronicConfigurations.Types.Pump.None
    "Actual pump input value that is used for computations"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput P(
    quantity="Power",
    final unit="W") if typ<>Buildings.Fluid.HydronicConfigurations.Types.Pump.None
    "Electrical power consumed"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort
    if typ<>Buildings.Fluid.HydronicConfigurations.Types.Pump.None
    "Heat dissipation to environment"

  Movers.FlowControlled_dp pumDp(
    redeclare final package Medium = Medium,
    final energyDynamics=energyDynamics,
    final p_start=p_start,
    final T_start=T_start,
    final X_start=X_start,
    final C_start=C_start,
    final C_nominal=C_nominal,
    final m_flow_nominal=m_flow_nominal,
    final m_flow_small=m_flow_small,
    final show_T=show_T,
    final inputType=Buildings.Fluid.Types.InputType.Continuous,
    final addPowerToMedium=addPowerToMedium,
    final use_riseTime=use_riseTime,
    final riseTime=riseTime,
    final init=init,
    final per=per) if typ <> Buildings.Fluid.HydronicConfigurations.Types.Pump.None
     and typMod == Buildings.Fluid.HydronicConfigurations.Types.PumpModel.Head
    "Pump with ideally controlled head as input signal"

  Movers.SpeedControlled_y pumSpe(
    redeclare final package Medium = Medium,
    final energyDynamics=energyDynamics,
    final p_start=p_start,
    final T_start=T_start,
    final X_start=X_start,
    final C_start=C_start,
    final C_nominal=C_nominal,
    final m_flow_small=m_flow_small,
    final show_T=show_T,
    final inputType=Buildings.Fluid.Types.InputType.Continuous,
    final addPowerToMedium=addPowerToMedium,
    final use_riseTime=use_riseTime,
    final riseTime=riseTime,
    final init=init,
    final per=per) if typ <> Buildings.Fluid.HydronicConfigurations.Types.Pump.None
     and typMod == Buildings.Fluid.HydronicConfigurations.Types.PumpModel.Speed
    "Pump with ideally controlled normalized speed as input"

  Movers.FlowControlled_m_flow pumFlo(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final energyDynamics=energyDynamics,
    final p_start=p_start,
    final T_start=T_start,
    final X_start=X_start,
    final C_start=C_start,
    final C_nominal=C_nominal,
    final m_flow_small=m_flow_small,
    final show_T=show_T,
    final inputType=Buildings.Fluid.Types.InputType.Continuous,
    final addPowerToMedium=addPowerToMedium,
    final use_riseTime=use_riseTime,
    final riseTime=riseTime,
    final init=init,
    final per=per) if typ <> Buildings.Fluid.HydronicConfigurations.Types.Pump.None
     and typMod == Buildings.Fluid.HydronicConfigurations.Types.PumpModel.MassFlowRate
    "Pump with ideally controlled mass flow rate as input"
  Sensors.VolumeFlowRate V_flow(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal)
    "Volume flow rate"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter scaHea(
    final k=dp_nominal)
    if typ<>Buildings.Fluid.HydronicConfigurations.Types.Pump.None
    "Scale control input to design head"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter scaSpe(
    final k=per.speed_nominal)
    if typ<>Buildings.Fluid.HydronicConfigurations.Types.Pump.None
    "Scale control input to design speed"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter scaFlo(
    final k=m_flow_nominal)
    if typ<>Buildings.Fluid.HydronicConfigurations.Types.Pump.None
    "Scale control input to design flow rate"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(final k=0.0)
               "Zero"
  Buildings.Controls.OBC.CDL.Reals.Switch swi
    if typ<>Buildings.Fluid.HydronicConfigurations.Types.Pump.None
    "Switch on/off"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant One(final k=1.0)
    if typ==Buildings.Fluid.HydronicConfigurations.Types.Pump.NoVariableInput
    "one"
  FixedResistances.LosslessPipe noPum(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal)
    if typ==Buildings.Fluid.HydronicConfigurations.Types.Pump.None
    "Direct fluid pass-through in case of no pump"
protected
  final parameter Modelica.Units.SI.Density rho_default=Medium.density_pTX(
      p=Medium.p_default,
      T=Medium.T_default,
      X=Medium.X_default) "Default medium density";

  final parameter Medium.ThermodynamicState sta_start=Medium.setState_pTX(
    T=T_start,
    p=p_start,
    X=X_start) "Medium state at start values";

  final parameter Modelica.Units.SI.SpecificEnthalpy h_outflow_start=
      Medium.specificEnthalpy(sta_start) "Start value for outflowing enthalpy";

equation
  connect(pumDp.port_b, port_b)
  connect(pumSpe.port_b, port_b)
  connect(pumDp.heatPort, heatPort)
  connect(pumSpe.heatPort, heatPort)
  connect(pumFlo.heatPort, heatPort)
  connect(pumFlo.port_b, port_b)
  connect(pumDp.P, P)
  connect(pumDp.y_actual, y_actual)
  connect(pumSpe.P, P)
  connect(pumSpe.y_actual, y_actual)
  connect(pumFlo.P, P)
  connect(pumFlo.y_actual, y_actual)
  connect(port_a, V_flow.port_a)
  connect(V_flow.port_b, pumSpe.port_a)
  connect(V_flow.port_b, pumDp.port_a)
  connect(V_flow.port_b, pumFlo.port_a)
  connect(scaHea.y, pumDp.dp_in)
  connect(scaSpe.y, pumSpe.y)
  connect(scaFlo.y, pumFlo.m_flow_in)
  connect(zer.y, swi.u3)
  connect(y, swi.u1)
  connect(y1, swi.u2)
  connect(swi.y, scaHea.u)
  connect(swi.y, scaSpe.u)
  connect(swi.y, scaFlo.u)
  connect(One.y, swi.u1)
  connect(V_flow.port_b, noPum.port_a)
  connect(noPum.port_b, port_b)
end Pump;