within Buildings.DHC.Networks.BaseClasses;
partial model PartialConnection2Pipe
  "Partial model for connecting an agent to a two-pipe distribution network"
  extends
    Buildings.DHC.Networks.BaseClasses.PartialConnection2Pipe2Medium(
    redeclare final package MediumSup=Medium,
    redeclare final package MediumRet=Medium);
  replaceable package Medium=Modelica.Media.Interfaces.PartialMedium
    "Medium model";
  replaceable model Model_pipCon=Fluid.Interfaces.PartialTwoPortInterface (
    redeclare final package Medium=Medium,
    final m_flow_nominal=mCon_flow_nominal,
    final allowFlowReversal=allowFlowReversal);
  parameter Boolean show_entFlo=false
    "Set to true to output enthalpy flow rate difference"

  // OUTPUTS
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput mCon_flow(
    final quantity="MassFlowRate",
    final unit="kg/s")
    "Connection supply mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dp(
    final quantity="PressureDifference",
    final unit="Pa",
    final displayUnit="Pa")
    "Pressure drop accross the connection (measured)"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dH_flow(
    final unit="W") if show_entFlo
    "Difference in enthalpy flow rate between connection supply and return"
  // COMPONENTS
  Model_pipCon pipCon
    "Connection pipe"
  Buildings.Fluid.Sensors.MassFlowRate senMasFloCon(
    redeclare final package Medium=Medium,
    final allowFlowReversal=allowFlowReversal)
    "Connection supply mass flow rate (measured)"
  Fluid.Sensors.RelativePressure senRelPre(
    redeclare final package Medium=Medium)
    "Relative pressure sensor"
  DifferenceEnthalpyFlowRate senDifEntFlo(
    redeclare final package Medium1 = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=mCon_flow_nominal) if show_entFlo
    "Difference in enthalpy flow rate"
equation
  // Connect statements involving conditionally removed components are
  // removed at translation time by Modelica specification.
  // Only obsolete statements corresponding to the default model structure need
  // to be programmatically removed.
  if not show_entFlo then
    connect(port_bCon,senMasFloCon.port_b)
    connect(port_aCon, junConRet.port_3)
  end if;
  connect(senMasFloCon.m_flow,mCon_flow)
  connect(senRelPre.port_a,junConSup.port_1)
  connect(senRelPre.port_b,junConRet.port_2)
  connect(senRelPre.p_rel,dp)
  connect(port_bCon, senDifEntFlo.port_b1)
  connect(senDifEntFlo.port_a2, port_aCon)
  connect(senDifEntFlo.dH_flow, dH_flow)
  connect(senMasFloCon.port_b, senDifEntFlo.port_a1)
  connect(senDifEntFlo.port_b2, junConRet.port_3)
  connect(pipCon.port_a, junConSup.port_3)
  connect(senMasFloCon.port_a, pipCon.port_b)
  connect(pipDisSup.port_b, junConSup.port_1)
  connect(pipDisRet.port_a, junConRet.port_2)
end PartialConnection2Pipe;


within Buildings.DHC.Networks.BaseClasses;
partial model PartialConnection2Pipe2Medium "Partial model for connecting an
  agent to a two-pipe distribution network with two medium declarations"
  replaceable package MediumSup = Modelica.Media.Interfaces.PartialMedium
    "Medium model for supply fluid";
  replaceable package MediumRet = Modelica.Media.Interfaces.PartialMedium
    "Medium model for return fluid";
  replaceable model Model_pipDisSup = Buildings.Fluid.Interfaces.PartialTwoPortInterface
      constrainedby Buildings.Fluid.Interfaces.PartialTwoPortInterface(
        redeclare final package Medium = MediumSup,
        final m_flow_nominal=mDis_flow_nominal,
        final allowFlowReversal=allowFlowReversal)
    "Interface for inlet pipe for the distribution supply";
  replaceable model Model_pipDisRet = Buildings.Fluid.Interfaces.PartialTwoPortInterface
      constrainedby Buildings.Fluid.Interfaces.PartialTwoPortInterface(
        redeclare final package Medium = MediumRet,
        final m_flow_nominal=mDis_flow_nominal,
        final allowFlowReversal=allowFlowReversal)
    "Interface for outlet pipe for the distribution return";

  parameter Modelica.Units.SI.MassFlowRate mDis_flow_nominal
    "Nominal mass flow rate in the distribution line"
  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal
    "Nominal mass flow rate in the connection line"
  parameter Boolean allowFlowReversal = false
    "= true to allow flow reversal, false restricts to design direction (port_a -> port_b)"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=
    Modelica.Fluid.Types.Dynamics.FixedInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  parameter Modelica.Units.SI.Time tau=10
    "Time constant at nominal flow for dynamic energy and momentum balance"

  // IO CONNECTORS
  Modelica.Fluid.Interfaces.FluidPort_a port_aDisSup(
    redeclare final package Medium = MediumSup,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumSup.h_default, nominal=MediumSup.h_default))
    "Distribution supply inlet port"
  Modelica.Fluid.Interfaces.FluidPort_b port_bDisSup(
    redeclare final package Medium = MediumSup,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumSup.h_default, nominal=MediumSup.h_default))
    "Distribution supply outlet port"
  Modelica.Fluid.Interfaces.FluidPort_a port_aDisRet(
    redeclare final package Medium = MediumRet,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumRet.h_default, nominal=MediumRet.h_default))
    "Distribution return inlet port"
  Modelica.Fluid.Interfaces.FluidPort_b port_bDisRet(
    redeclare final package Medium = MediumRet,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumRet.h_default, nominal=MediumRet.h_default))
    "Distribution return outlet port"
  Modelica.Fluid.Interfaces.FluidPort_b port_bCon(
    redeclare final package Medium = MediumSup,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumSup.h_default, nominal=MediumSup.h_default))
    "Connection supply port"
  Modelica.Fluid.Interfaces.FluidPort_a port_aCon(
    redeclare final package Medium = MediumRet,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumRet.h_default, nominal=MediumRet.h_default))
    "Connection return port"
  // COMPONENTS
  Model_pipDisSup pipDisSup "Distribution supply pipe"
  Model_pipDisRet pipDisRet "Distribution return pipe"
  Buildings.Fluid.FixedResistances.Junction junConSup(
    redeclare final package Medium = MediumSup,
    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 dp_nominal = {0, 0, 0},
    final energyDynamics=energyDynamics,
    final tau=tau,
    final m_flow_nominal={mDis_flow_nominal,-mDis_flow_nominal,-mCon_flow_nominal})
    "Junction with connection supply"
  Buildings.Fluid.FixedResistances.Junction junConRet(
    redeclare final package Medium = MediumRet,
    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 dp_nominal = {0, 0, 0},
    final energyDynamics=energyDynamics,
    final tau=tau,
    final m_flow_nominal={mDis_flow_nominal,-mDis_flow_nominal,mCon_flow_nominal})
    "Junction with connection return"
protected
  parameter Modelica.Units.SI.SpecificHeatCapacity cp_default=
    MediumRet.specificHeatCapacityCp(MediumRet.setState_pTX(
      p = MediumRet.p_default,
      T = MediumRet.T_default,
      X = MediumRet.X_default))
    "Specific heat capacity of medium at default medium state";
equation
  connect(port_aDisSup, pipDisSup.port_a)
  connect(pipDisRet.port_b, port_bDisRet)
  connect(junConSup.port_2, port_bDisSup)
  connect(junConRet.port_1, port_aDisRet)
end PartialConnection2Pipe2Medium;


Partial model for distribution network

within Buildings.DHC.Networks.BaseClasses;
partial model PartialDistribution
  "Partial model for distribution network"
  extends Buildings.DHC.Networks.BaseClasses.PartialDistribution2Medium(
    redeclare final package MediumSup=Medium,
    redeclare final package MediumRet=Medium);
  replaceable package Medium=Modelica.Media.Interfaces.PartialMedium
    "Medium model"
end PartialDistribution;


within Buildings.DHC.Networks.BaseClasses;
partial model PartialDistribution1Pipe
  "Partial model for one-pipe distribution network"
  extends PartialDistribution;
  replaceable model Model_pipDis=Fluid.Interfaces.PartialTwoPortInterface (
    redeclare final package Medium=Medium,
    final allowFlowReversal=allowFlowReversal)
    "Model for distribution pipe";
  parameter Boolean show_entFlo=false
    "Set to true to output enthalpy flow rate difference at each connection"
  parameter Boolean show_TOut=false
    "Set to true to output temperature at connection outlet"
  parameter Modelica.Units.SI.MassFlowRate mDis_flow_nominal
    "Nominal mass flow rate in the distribution line"
  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal[nCon]
    "Nominal mass flow rate in each connection line"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  parameter Modelica.Units.SI.Time tau=10
    "Time constant at nominal flow for dynamic energy and momentum balance"
  // IO CONNECTORS
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dH_flow[nCon](
    each final unit="W") if show_entFlo
    "Difference in enthalpy flow rate between connection supply and return"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput mCon_flow[nCon](
    each final unit="kg/s")
    "Connection supply mass flow rate (measured)"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput mByp_flow[nCon](
    each final unit="kg/s")
    "Bypass mass flow rate"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TOut[nCon](
    each final unit="K",
    each displayUnit="degC") if show_TOut
    "Temperature in distribution line at each connection outlet"
  // COMPONENTS
  replaceable PartialConnection1Pipe con[nCon](
    redeclare each final package Medium=Medium,
    each final show_entFlo=show_entFlo,
    each final show_TOut=show_TOut,
    each final mDis_flow_nominal=mDis_flow_nominal,
    final mCon_flow_nominal=mCon_flow_nominal,
    each final allowFlowReversal=allowFlowReversal,
    each final energyDynamics=energyDynamics,
    each final tau=tau)
    "Connection to agent"
  Model_pipDis pipEnd(
    final m_flow_nominal=mDis_flow_nominal)
    "Pipe representing the end of the distribution line (after last connection)"
equation
  // Connecting outlets to inlets for all instances of connection component.
  if nCon >= 2 then
    for i in 2:nCon loop
      connect(con[i-1].port_bDis,con[i].port_aDis);
    end for;
  end if;
  connect(con.port_bCon,ports_bCon)
  connect(ports_aCon,con.port_aCon)
  connect(port_aDisSup,con[1].port_aDis)
  connect(con[nCon].port_bDis,pipEnd.port_a)
  connect(pipEnd.port_b,port_bDisSup)
  connect(con.mByp_flow,mByp_flow)
  connect(con.mCon_flow,mCon_flow)
  connect(con.dH_flow, dH_flow)
  connect(con.TOut, TOut)
end PartialDistribution1Pipe;


within Buildings.DHC.Networks.BaseClasses;
partial model PartialDistribution2Medium
  "Partial model for distribution network with two medium declarations"
  replaceable package MediumSup =
      Modelica.Media.Interfaces.PartialMedium
    "Medium model for supply fluid";
  replaceable package MediumRet =
      Modelica.Media.Interfaces.PartialMedium
    "Medium model for return fluid";
  parameter Integer nCon(min=1)
    "Number of connections"
  parameter Boolean allowFlowReversal=false
    "= true to allow flow reversal, false restricts to design direction (port_a -> port_b)"
  // IO CONNECTORS
  Modelica.Fluid.Interfaces.FluidPorts_a ports_aCon[nCon](
    redeclare each final package Medium=MediumRet,
    each m_flow(
      min=
        if allowFlowReversal then
          -Modelica.Constants.inf
        else
          0),
    each h_outflow(
      start=MediumRet.h_default,
      nominal=MediumRet.h_default))
    "Connection return ports"
  Modelica.Fluid.Interfaces.FluidPorts_b ports_bCon[nCon](
    redeclare each package Medium=MediumSup,
    each m_flow(
      max=
        if allowFlowReversal then
          +Modelica.Constants.inf
        else
          0),
    each h_outflow(
      start=MediumSup.h_default,
      nominal=MediumSup.h_default))
    "Connection supply ports"
  Modelica.Fluid.Interfaces.FluidPort_a port_aDisSup(
    redeclare final package Medium=MediumSup,
    m_flow(
      min=
        if allowFlowReversal then
          -Modelica.Constants.inf
        else
          0),
    h_outflow(
      start=MediumSup.h_default,
      nominal=MediumSup.h_default))
    "Distribution supply inlet port"
  Modelica.Fluid.Interfaces.FluidPort_b port_bDisSup(
    redeclare final package Medium=MediumSup,
    m_flow(
      max=
        if allowFlowReversal then
          +Modelica.Constants.inf
        else
          0),
    h_outflow(
      start=MediumRet.h_default,
      nominal=MediumRet.h_default))
    "Distribution supply outlet port"
end PartialDistribution2Medium;


within Buildings.DHC.Networks.BaseClasses;
partial model PartialDistribution2Pipe
  "Partial model for two-pipe distribution network"
  extends PartialDistribution;
  replaceable model Model_pipDis=Fluid.Interfaces.PartialTwoPortInterface (
    redeclare final package Medium=Medium,
    final allowFlowReversal=allowFlowReversal)
    "Model for distribution pipe";
  parameter Integer iConDpSen(
    final max=nCon)=nCon
    "Index of the connection where the pressure drop is measured"
  parameter Boolean show_entFlo=false
    "Set to true to output enthalpy flow rate difference at each connection"
  parameter Modelica.Units.SI.MassFlowRate mDis_flow_nominal
    "Nominal mass flow rate in the distribution line before the first connection"
  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal[nCon]
    "Nominal mass flow rate in each connection line"
  parameter Modelica.Units.SI.MassFlowRate mEnd_flow_nominal=mDis_flow_nominal
       - sum(mCon_flow_nominal)
    "Nominal mass flow rate in the end of the distribution line"
  parameter Modelica.Units.SI.MassFlowRate mDisCon_flow_nominal[nCon]=cat(
      1,
      {mDis_flow_nominal},
      {mDis_flow_nominal - sum(mCon_flow_nominal[1:i]) for i in 1:(nCon - 1)})
    "Nominal mass flow rate in the distribution line before each connection"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  parameter Modelica.Units.SI.Time tau=10
    "Time constant at nominal flow for dynamic energy and momentum balance"
  // IO CONNECTORS
  Modelica.Fluid.Interfaces.FluidPort_b port_bDisRet(
    redeclare final package Medium=Medium,
    m_flow(
      max=
        if allowFlowReversal then
          +Modelica.Constants.inf
        else
          0),
    h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    "Distribution return outlet port"
  Modelica.Fluid.Interfaces.FluidPort_a port_aDisRet(
    redeclare final package Medium=Medium,
    m_flow(
      min=
        if allowFlowReversal then
          -Modelica.Constants.inf
        else
          0),
    h_outflow(
      start=Medium.h_default,
      nominal=Medium.h_default))
    "Distribution return inlet port"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dp(
    final unit="Pa",
    displayUnit="Pa") if iConDpSen >= 0
    "Pressure difference at given location (measured)"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput dH_flow[nCon](each final
      unit="W")          if show_entFlo
    "Difference in enthalpy flow rate between connection supply and return"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput mCon_flow[nCon](
    each final unit="kg/s")
    "Connection supply mass flow rate (measured)"
  // COMPONENTS
  replaceable Buildings.DHC.Networks.BaseClasses.PartialConnection2Pipe con[nCon](
    redeclare each final package Medium=Medium,
    each final show_entFlo=show_entFlo,
    final mDis_flow_nominal=mDisCon_flow_nominal,
    final mCon_flow_nominal=mCon_flow_nominal,
    each final allowFlowReversal=allowFlowReversal,
    each final energyDynamics=energyDynamics,
    each final tau=tau)
    "Connection to agent"
  Model_pipDis pipEnd(
    final m_flow_nominal=mEnd_flow_nominal)
    "Pipe representing the end of the distribution line (after last connection)"
  Fluid.Sensors.RelativePressure senRelPre(
    redeclare final package Medium=Medium) if iConDpSen == 0
    "Relative pressure sensor"
initial equation
  assert(
    iConDpSen <= nCon,
    "In "+getInstanceName()+": iConDpSen = "+String(
      iConDpSen)+" whereas it must be lower than "+String(
      nCon)+".");
equation
  // Connecting outlets to inlets for all instances of connection component.
  if nCon >= 2 then
    for i in 2:nCon loop
      connect(con[i-1].port_bDisSup,con[i].port_aDisSup);
      connect(con[i-1].port_aDisRet,con[i].port_bDisRet);
    end for;
  end if;
  // Connecting dp sensor (needs to be explicit because con[iConDpSen] is
  // undefined if iConDpSen <= 0).
  if iConDpSen > 0 then
    connect(con[iConDpSen].dp,dp)
  end if;
  connect(senRelPre.p_rel,dp)
  connect(con.port_bCon,ports_bCon)
  connect(ports_aCon,con.port_aCon)
  connect(port_aDisSup,con[1].port_aDisSup)
  connect(port_bDisRet,con[1].port_bDisRet)
  connect(con[nCon].port_aDisRet,port_aDisRet)
  connect(con[nCon].port_bDisSup,pipEnd.port_a)
  connect(pipEnd.port_b,port_bDisSup)
  connect(con.mCon_flow,mCon_flow)
  connect(port_aDisSup,senRelPre.port_a)
  connect(senRelPre.port_b,port_bDisRet)
  connect(con.dH_flow, dH_flow)
end PartialDistribution2Pipe;


within Buildings.DHC.Networks.BaseClasses;
partial model PartialDistribution2Pipe2Medium
  "Partial model for a two-pipe distribution network with two medium declarations"
  extends
    Buildings.DHC.Networks.BaseClasses.PartialDistribution2Medium;
  replaceable model Model_pipDis =
      Buildings.Fluid.Interfaces.PartialTwoPortInterface
      constrainedby Buildings.Fluid.Interfaces.PartialTwoPortInterface(
        redeclare final package Medium = MediumSup,
        final allowFlowReversal=allowFlowReversal)
    "Model for distribution pipe";
  parameter Boolean show_heaFlo=false
    "Set to true to output the heat flow rate transferred to each connected load"
  parameter Modelica.Units.SI.MassFlowRate mDis_flow_nominal
    "Nominal mass flow rate in the distribution line before the first connection"
  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal[nCon]
    "Nominal mass flow rate in each connection line"
  parameter Modelica.Units.SI.MassFlowRate mEnd_flow_nominal=mDis_flow_nominal-sum(
    mCon_flow_nominal)
    "Nominal mass flow rate in the end of the distribution line"
  parameter Modelica.Units.SI.MassFlowRate mDisCon_flow_nominal[nCon]=cat(
    1,
    {mDis_flow_nominal},
    {mDis_flow_nominal-sum(mCon_flow_nominal[1:i]) for i in 1:(nCon-1)})
    "Nominal mass flow rate in the distribution line before each connection"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  parameter Modelica.Units.SI.Time tau=10
    "Time constant at nominal flow for dynamic energy and momentum balance"
  // IO CONNECTORS
  Modelica.Fluid.Interfaces.FluidPort_b port_bDisRet(
    redeclare final package Medium=MediumRet,
    m_flow(
      max=
        if allowFlowReversal then
          +Modelica.Constants.inf
        else
          0),
    h_outflow(
      start=MediumRet.h_default,
      nominal=MediumRet.h_default))
    "Distribution return outlet port"
  Modelica.Fluid.Interfaces.FluidPort_a port_aDisRet(
    redeclare final package Medium=MediumRet,
    m_flow(
      min=
        if allowFlowReversal then
          -Modelica.Constants.inf
        else
          0),
    h_outflow(
      start=MediumRet.h_default,
      nominal=MediumRet.h_default))
    "Distribution return inlet port"
  // COMPONENTS
  replaceable
    Buildings.DHC.Networks.BaseClasses.PartialConnection2Pipe2Medium
    con[nCon]
    constrainedby Buildings.DHC.Networks.BaseClasses.PartialConnection2Pipe2Medium(
    redeclare each final package MediumSup = MediumSup,
    redeclare each final package MediumRet = MediumRet,
    final mDis_flow_nominal=mDisCon_flow_nominal,
    final mCon_flow_nominal=mCon_flow_nominal,
    each final allowFlowReversal=allowFlowReversal,
    each final energyDynamics=energyDynamics,
    each final tau=tau) "Connection to agent"
  Model_pipDis pipEnd(
    final m_flow_nominal=mEnd_flow_nominal)
    "Pipe representing the end of the distribution line (after last connection)"
initial equation
  assert(
    mDis_flow_nominal >= sum(
      mCon_flow_nominal),
    "In "+getInstanceName()+": mDis_flow_nominal = "+String(
      mDis_flow_nominal)+" whereas it must be higher than sum(mCon_flow_nominal) = "+String(
      sum(
        mCon_flow_nominal))+".");
equation
  // Connecting outlets to inlets for all instances of connection component.
  if nCon >= 2 then
    for i in 2:nCon loop
      connect(con[i-1].port_bDisSup,con[i].port_aDisSup);
      connect(con[i-1].port_aDisRet,con[i].port_bDisRet);
    end for;
  end if;
  connect(con.port_bCon,ports_bCon)
  connect(ports_aCon,con.port_aCon)
  connect(port_aDisSup,con[1].port_aDisSup)
  connect(port_bDisRet,con[1].port_bDisRet)
  connect(con[nCon].port_aDisRet,port_aDisRet)
  connect(con[nCon].port_bDisSup,pipEnd.port_a)
  connect(pipEnd.port_b,port_bDisSup)
end PartialDistribution2Pipe2Medium;


Model for connecting an agent to the DHC system. This model represents the supply and return lines to connect an
agent (e.g. an energy transfer station) to a one-pipe main distribution
system.  A plug flow pipe model
Buildings.Fluid.FixedResistances.PlugFlowPipe that includes pressure drop, heat transfer, and transport
delays is used in the main distribution line,
but not in the connection to the building, as the latter is typically short.

within Buildings.DHC.Networks.Connections;
model Connection1PipePlugFlow_v
  "Model for connecting an agent to the DHC system"
  extends Buildings.DHC.Networks.BaseClasses.PartialConnection1Pipe(
    tau=5*60,
    redeclare replaceable model Model_pipDis = Buildings.Fluid.FixedResistances.PlugFlowPipe(
      final length=lDis,
      final dIns=dIns,
      final kIns=kIns,
      v_nominal=v_nominal,
      roughness=roughness,
      cPip=cPip,
      rhoPip=rhoPip,
      thickness=thickness),
    redeclare replaceable model Model_pipCon = Buildings.Fluid.FixedResistances.LosslessPipe);

  parameter Modelica.Units.SI.Length dIns
    "Thickness of pipe insulation, used to compute R"
  parameter Modelica.Units.SI.ThermalConductivity kIns
    "Heat conductivity of pipe insulation, used to compute R"
  parameter Modelica.Units.SI.Length lDis
    "Length of the distribution pipe before the connection";
  parameter Modelica.Units.SI.Velocity v_nominal=1.5
    "Velocity at m_flow_nominal (used to compute default value for hydraulic diameter dh)";
  parameter Modelica.Units.SI.Height roughness=2.5e-5
    "Average height of surface asperities (default: smooth steel pipe)";
  parameter Modelica.Units.SI.SpecificHeatCapacity cPip=2300
    "Specific heat of pipe wall material. 2300 for PE, 500 for steel";
  parameter Modelica.Units.SI.Density rhoPip=930
    "Density of pipe wall material. 930 for PE, 8000 for steel";
  parameter Modelica.Units.SI.Length thickness=0.0035 "Pipe wall thickness";
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPortDis
    "Heat transfer to and from the distribution pipe"

equation
  connect(pipDis.heatPort, heatPortDis)
end Connection1PipePlugFlow_v;


Model for connecting an agent to the DHC system. This model represents the supply and return lines to connect an
agent (e.g., an energy transfer station) to a one-pipe main distribution
system. The instances of the pipe model are autosized based on the pressure drop per pipe length
at nominal flow rate based on the model
Buildings.DHC.Networks.Pipes.PipeAutosize for the distribution line. The connection to the building as the length is typically relatively short so a losssless pipe is considered.

within Buildings.DHC.Networks.Connections;
model Connection1Pipe_R "Model for connecting an agent to the DHC system"
  extends Buildings.DHC.Networks.BaseClasses.PartialConnection1Pipe(
    tau=5*60,
    redeclare replaceable model Model_pipDis = Pipes.PipeAutosize(
        roughness = 7e-6,
        final length = lDis,
        dh(fixed=true) = dhDis,
        final dp_length_nominal = dp_length_nominal),
    redeclare replaceable model Model_pipCon = Buildings.Fluid.FixedResistances.LosslessPipe,
    pipDis(fac=1));
  parameter Real dp_length_nominal(final unit="Pa/m") = 250
    "Pressure drop per pipe length at nominal flow rate";
  parameter Modelica.Units.SI.Length lDis
    "Length of the distribution pipe before the connection";
  parameter Modelica.Units.SI.Length dhDis
    "Hydraulic diameter of the distribution pipe";
end Connection1Pipe_R;


Model for connecting an agent to a two-pipe distribution network, using plug flow pipe models in the main line. This model represents the supply and return lines to connect an
agent (e.g. an energy transfer station) to a two-pipe main distribution
system.  A plug flow pipe model
Buildings.Fluid.FixedResistances.PlugFlowPipe that includes pressure drop, heat transfer, and transport
delays is used in the main distribution line,
but not in the connection to the building, as the latter is typically short.

within Buildings.DHC.Networks.Connections;
model Connection2PipePlugFlow_v
  "Model for connecting an agent to a two-pipe distribution network, using plug flow pipe models in the main line"
  extends Buildings.DHC.Networks.BaseClasses.PartialConnection2Pipe(
    redeclare model Model_pipDisSup = Buildings.Fluid.FixedResistances.PlugFlowPipe(
      final length = lDis,
      final dIns = dIns,
      final kIns = kIns,
      v_nominal = v_nominal,
      roughness = roughness,
      cPip = cPip,
      rhoPip = rhoPip,
      thickness = thickness),
    redeclare model Model_pipDisRet = Buildings.Fluid.FixedResistances.PlugFlowPipe (
      final length = lDis,
      final dIns = dIns,
      final kIns = kIns,
      v_nominal = v_nominal,
      roughness = roughness,
      cPip = cPip,
      rhoPip = rhoPip,
      thickness = thickness),
    redeclare model Model_pipCon = Fluid.FixedResistances.LosslessPipe);
  parameter Modelica.Units.SI.Length lDis
    "Length of the distribution pipe before the connection";
  parameter Modelica.Units.SI.Length dIns
    "Thickness of pipe insulation, used to compute R";
  parameter Modelica.Units.SI.ThermalConductivity kIns
    "Heat conductivity of pipe insulation, used to compute R";
  parameter Modelica.Units.SI.Velocity v_nominal = 1.5
    "Velocity at m_flow_nominal (used to compute default value for hydraulic diameter dh)";
  parameter Modelica.Units.SI.Height roughness = 2.5e-5
    "Average height of surface asperities (default: smooth steel pipe)";
  parameter Modelica.Units.SI.SpecificHeatCapacity cPip = 2300
    "Specific heat of pipe wall material. 2300 for PE, 500 for steel";
  parameter Modelica.Units.SI.Density rhoPip = 930
    "Density of pipe wall material. 930 for PE, 8000 for steel";
  parameter Modelica.Units.SI.Length thickness = 0.0035 "Pipe wall thickness";
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPortDis
    "Heat transfer to or from surroundings for distribution pipe(positive if pipe is colder than surrounding)"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPortRet
    "Heat transfer to or from surroundings for return pipe (positive if pipe is colder than surrounding)"
equation
  connect(pipDisSup.heatPort, heatPortDis)
  connect(pipDisRet.heatPort, heatPortRet)
end Connection2PipePlugFlow_v;


Model for connecting an agent to the DHC system. This model represents the supply and return lines to connect an
agent (e.g., an energy transfer station) to a two-pipe main distribution
system. The instances of the pipe model are autosized based on the pressure drop per pipe length
at nominal flow rate based on the model
Buildings.DHC.Networks.Pipes.PipeAutosize for the distribution line. The connection to the building as the length is typically relatively short so a losssless pipe is considered.

within Buildings.DHC.Networks.Connections;
model Connection2Pipe_R
  "Model for connecting an agent to the DHC system"
  extends Buildings.DHC.Networks.BaseClasses.PartialConnection2Pipe(
    tau=5*60,
    redeclare replaceable model Model_pipDisSup = Pipes.PipeAutosize(
        roughness = 7e-6,
        dh(fixed=true) = dhDis,
        final length = lDis,
        final dp_length_nominal = dp_length_nominal),
    redeclare replaceable model Model_pipDisRet = Pipes.PipeAutosize(
        roughness=7e-6,
        dh(fixed=true) = dhDisRet,
        final length=lDis,
        final dp_length_nominal=dp_length_nominal),
     redeclare model Model_pipCon = Fluid.FixedResistances.LosslessPipe,
    pipDisSup(fac=1),
    pipDisRet(fac=1));
  parameter Real dp_length_nominal(final unit="Pa/m") = 250
    "Pressure drop per pipe length at nominal flow rate";
  parameter Modelica.Units.SI.Length dhDisRet
    "Hydraulic diameter of the return distribution pipe";
  parameter Modelica.Units.SI.Length lDis
    "Length of the distribution pipe before the connection";
  parameter Modelica.Units.SI.Length dhDis
    "Hydraulic diameter of the distribution pipe";
end Connection2Pipe_R;


within Buildings.DHC.Networks;
package Connections "Package containing various configurations for connecting network participants to a distribution network"
  extends Modelica.Icons.VariantsPackage;
end Connections;


within Buildings.DHC.Networks.Connections.Examples;
model Connection1PipeExample
  "Example model that showcases Connection1Pipe_R and Connection1PipePlugFlow_v models"
  extends Modelica.Icons.Example;
    package MediumW = Buildings.Media.Water "Medium model";
  parameter Modelica.Units.SI.Length dh(
    fixed=false,
    start=0.01,
    min=0.001) "Hydraulic diameter (assuming a round cross section area)";
  parameter Modelica.Units.SI.MassFlowRate mDis_flow_nominal = 1
    "Nominal mass flow rate in the distribution line";
  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal = 0.5
    "Nominal mass flow rate in the connection line";
  parameter Modelica.Units.SI.Length lDis = 100
    "Length of the distribution pipe before the connection";
  Buildings.DHC.Networks.Connections.Connection1Pipe_R connection1Pipe_R(
    redeclare package Medium = MediumW,
    mDis_flow_nominal=mDis_flow_nominal,
    mCon_flow_nominal=mCon_flow_nominal,
    lDis=lDis,
    dhDis=dh)
  Buildings.Fluid.Sources.Boundary_pT bouDisAutoSize(
    redeclare final package Medium = MediumW,
    p=300000,
    nPorts=1)
  Modelica.Blocks.Sources.Constant mDis_flow_nominal_exp(k=mDis_flow_nominal)
  Buildings.DHC.ETS.BaseClasses.Pump_m_flow pumDisPipe_R(
    dp_nominal=100000,
    redeclare final package Medium = MediumW,
    m_flow_nominal=mDis_flow_nominal) "Distribution network pump"

  Buildings.DHC.ETS.BaseClasses.Pump_m_flow pumConPipe_R(
    dp_nominal=5000,
    redeclare final package Medium = MediumW,
    m_flow_nominal=mDis_flow_nominal) "Agent connection pump"
  Buildings.DHC.Networks.Connections.Connection1PipePlugFlow_v
    connection1PipeplugFlow(
    redeclare package Medium = MediumW,
    mDis_flow_nominal=mDis_flow_nominal,
    mCon_flow_nominal=mCon_flow_nominal,
    dIns=0.001,
    kIns=1,
    lDis=lDis)
  Buildings.Fluid.Sources.Boundary_pT bouDisPlugFlow(
    redeclare final package Medium = MediumW,
    p=300000,
    nPorts=1)
  Buildings.DHC.ETS.BaseClasses.Pump_m_flow pumDisPlugFlow(
    dp_nominal=100000,
    redeclare final package Medium = MediumW,
    m_flow_nominal = mDis_flow_nominal) "Distribution network pump"
  Buildings.DHC.ETS.BaseClasses.Pump_m_flow pumConPlugFlow(
    dp_nominal=5000,
    redeclare final package Medium = MediumW,
    m_flow_nominal=mDis_flow_nominal) "Agent connection pump"
  Fluid.FixedResistances.BuriedPipes.PipeGroundCoupling pipeGroundCoupling(
    lPip=lDis,
    rPip=0.04,
    thiGroLay=1.1,
    nSta=5,
    nSeg=1)

  Modelica.Blocks.Sources.Step mCon_flow_nominal_exp(height=mCon_flow_nominal,
      startTime=1800)
equation
  connect(pumDisPipe_R.port_b, connection1Pipe_R.port_aDis)
  connect(bouDisAutoSize.ports[1], connection1Pipe_R.port_aDis)
  connect(pumDisPipe_R.port_a, connection1Pipe_R.port_bDis)
  connect(mDis_flow_nominal_exp.y, pumDisPipe_R.m_flow_in)
  connect(connection1Pipe_R.port_bCon, pumConPipe_R.port_a)
  connect(pumConPipe_R.port_b, connection1Pipe_R.port_aCon)
  connect(pumDisPlugFlow.port_b, connection1PipeplugFlow.port_aDis)
  connect(bouDisPlugFlow.ports[1], connection1PipeplugFlow.port_aDis)
  connect(pumDisPlugFlow.port_a, connection1PipeplugFlow.port_bDis)
  connect(mDis_flow_nominal_exp.y, pumDisPlugFlow.m_flow_in)
  connect(connection1PipeplugFlow.port_bCon, pumConPlugFlow.port_a)
  connect(pumConPlugFlow.port_b, connection1PipeplugFlow.port_aCon)
  connect(pipeGroundCoupling.heatPorts[1], connection1PipeplugFlow.heatPortDis)
  connect(mCon_flow_nominal_exp.y, pumConPipe_R.m_flow_in)
  connect(pumConPlugFlow.m_flow_in, pumConPipe_R.m_flow_in)
end Connection1PipeExample;


within Buildings.DHC.Networks.Connections.Examples;
model Connection2PipeExample
  "Example model that showcases Connection2Pipe_R and Connection2PipePlugFlow_v models"
  extends Modelica.Icons.Example;
    package MediumW = Buildings.Media.Water "Medium model";
  parameter Modelica.Units.SI.Length dhDis(
    fixed=false,
    start=0.01,
    min=0.001) "Hydraulic diameter (assuming a round cross section area)";
  parameter Modelica.Units.SI.Length dhRet(
    fixed=false,
    start=0.01,
    min=0.001) "Hydraulic diameter (assuming a round cross section area)";
  parameter Modelica.Units.SI.MassFlowRate mDis_flow_nominal=1
    "Nominal mass flow rate in the distribution line";
  parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal=0.5
    "Nominal mass flow rate in the connection line";
  parameter Modelica.Units.SI.Length lDis=100
    "Length of the distribution pipe before the connection";
  Buildings.DHC.Networks.Connections.Connection2Pipe_R connection2Pipe_R(
    redeclare package Medium = MediumW,
    mDis_flow_nominal=mDis_flow_nominal,
    mCon_flow_nominal=mCon_flow_nominal,
    dhDisRet=dhRet,
    lDis=lDis,
    dhDis=dhDis)
  Buildings.Fluid.Sources.Boundary_pT bouDisPipe_R(
    redeclare final package Medium = MediumW,
    p=300000,
    nPorts=1)
  Modelica.Blocks.Sources.Constant mDis_flow_nominal_exp(k=mDis_flow_nominal)
  Buildings.DHC.ETS.BaseClasses.Pump_m_flow pumDisPipe_R(
    dp_nominal=100000,
    redeclare final package Medium = MediumW,
    m_flow_nominal=mDis_flow_nominal) "Distribution network pump"

  Buildings.DHC.ETS.BaseClasses.Pump_m_flow pumConPipe_R(
    dp_nominal=5000,
    redeclare final package Medium = MediumW,
    m_flow_nominal=mDis_flow_nominal) "Agent connection pump"
  Buildings.DHC.Networks.Connections.Connection2PipePlugFlow_v
    connection2PipeplugFlow(
    redeclare package Medium = MediumW,
    mDis_flow_nominal=mDis_flow_nominal,
    mCon_flow_nominal=mCon_flow_nominal,
    dIns=0.001,
    kIns=1,
    lDis=lDis)
  Buildings.Fluid.Sources.Boundary_pT bouDisPlugFlow(
    redeclare final package Medium = MediumW,
    p=300000,
    nPorts=1)
  Buildings.DHC.ETS.BaseClasses.Pump_m_flow pumDisPlugFlow(
    dp_nominal=100000,
    redeclare final package Medium = MediumW,
    m_flow_nominal=mDis_flow_nominal) "Distribution network pump"
  Buildings.DHC.ETS.BaseClasses.Pump_m_flow pumConPlugFlow(
    dp_nominal=5000,
    redeclare final package Medium = MediumW,
    m_flow_nominal=mDis_flow_nominal) "Agent connection pump"
  Fluid.FixedResistances.BuriedPipes.PipeGroundCoupling pipeGroundCoupling(
    lPip=lDis,
    rPip=0.04,
    thiGroLay=1.1,
    nSta=5,
    nSeg=2)

  Modelica.Blocks.Sources.Step mCon_flow_nominal_exp(height=mCon_flow_nominal,
      startTime=1800)
  Fluid.Sensors.MassFlowRate senMasFloDisAutosize(redeclare final package
      Medium = MediumW) "Connection supply mass flow rate (measured)"
  Fluid.Sensors.MassFlowRate senMasFloDisPlugFlow(redeclare final package
      Medium = MediumW) "Connection supply mass flow rate (measured)"
equation
  connect(mDis_flow_nominal_exp.y, pumDisPipe_R.m_flow_in)
  connect(mDis_flow_nominal_exp.y, pumDisPlugFlow.m_flow_in)
  connect(connection2PipeplugFlow.port_bCon, pumConPlugFlow.port_a)
  connect(pumConPlugFlow.port_b,connection2PipeplugFlow. port_aCon)
  connect(pipeGroundCoupling.heatPorts[1],connection2PipeplugFlow. heatPortDis)
  connect(mCon_flow_nominal_exp.y, pumConPipe_R.m_flow_in)
  connect(pumConPlugFlow.m_flow_in, pumConPipe_R.m_flow_in)
  connect(pumDisPipe_R.port_a, connection2Pipe_R.port_bDisRet)
  connect(pumDisPlugFlow.port_a,connection2PipeplugFlow. port_bDisRet)
  connect(connection2PipeplugFlow.heatPortRet, pipeGroundCoupling.heatPorts[2])
  connect(pumDisPlugFlow.port_b, connection2PipeplugFlow.port_aDisSup)
  connect(pumDisPipe_R.port_b, connection2Pipe_R.port_aDisSup)
  connect(connection2Pipe_R.port_bCon, pumConPipe_R.port_a)
  connect(pumConPipe_R.port_b, connection2Pipe_R.port_aCon)
  connect(connection2Pipe_R.port_bDisSup, senMasFloDisAutosize.port_a)
  connect(senMasFloDisAutosize.port_b, connection2Pipe_R.port_aDisRet)
  connect(connection2PipeplugFlow.port_bDisSup, senMasFloDisPlugFlow.port_a)
  connect(senMasFloDisPlugFlow.port_b, connection2PipeplugFlow.port_aDisRet)
  connect(bouDisPlugFlow.ports[1], connection2PipeplugFlow.port_aDisSup)
  connect(bouDisPipe_R.ports[1], connection2Pipe_R.port_aDisSup)
end Connection2PipeExample;


This package contains example models

within Buildings.DHC.Networks.Connections;
package Examples "This package contains example models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Ambient network storage and plants agent pump control, developed for reservoir network. Controller for balacing agents (i.e. reservoirs and plants) pump.

within Buildings.DHC.Networks.Controls;
block AgentPump1Pipe
  "Ambient network storage and plants agent pump control, developed for reservoir network"
   parameter Buildings.Controls.OBC.CDL.Types.SimpleController controllerType =
      Buildings.Controls.OBC.CDL.Types.SimpleController.P "Type of controller";
   parameter Real yPumMin(min=0, max=1, final unit="1") = 0.05
    "Minimum pump speed";
   parameter Real yPumMax(min=0, max=1, final unit="1") = 1 "Upper limit of output";
   parameter Real k = 1 "Gain of controller";
   parameter Real Ti = 0.5 "Time constant of integrator block";
   parameter Real Td = 0.1 "Time constant of derivative block";
   parameter Modelica.Units.SI.TemperatureDifference dToff(min=0.1) = 1
    "Temperature offset to account for heat exchanger pinch point";
   parameter Real uLowHea = 1 "if y=true and u<uLow, switch to y=false";
   parameter Real uHighHea = 2 "if y=false and u>uHigh, switch to y=true";
   parameter Real uLowCoo = 1 "if y=true and u<uLow, switch to y=false";
   parameter Real uHighCoo = 2 "if y=false and u>uHigh, switch to y=true";
   parameter Real h = 0.15 "Hysteresis for net demand temperature calculation";

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TSouIn(final unit="K",
       displayUnit="degC") "Temperatures at the inlet of the source"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TSouOut(final unit="K",
      displayUnit="degC") "Agent supply temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TSou(final unit="K",
      displayUnit="degC") "Average temperature available at source"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TRetDis(final unit="K",
      displayUnit="degC") "District return temperature"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TSupDis(final unit="K",
      displayUnit="degC") "Plant supply temperature"

  Buildings.Controls.OBC.CDL.Reals.Less NetDemBool(h=h)
    "Net district demand boolean"
  Buildings.Controls.OBC.CDL.Reals.Switch swi
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput y(
    min=0,
    max=1,
    unit="1")
    "Pump control signal"
  Buildings.Controls.OBC.CDL.Reals.PID conPIDHea(
    controllerType=controllerType,
    k=k,
    Ti=Ti,
    Td=Td,
    yMax=yPumMax,
    yMin=yPumMin) "Controller to track target heating setpoint temperature"

  Buildings.Controls.OBC.CDL.Reals.PID conPIDCoo(
    controllerType=controllerType,
    k=k,
    Ti=Ti,
    Td=Td,
    yMax=yPumMax,
    yMin=yPumMin,
    reverseActing=false)
    "Controller to track target cooling setpoint temperature"

  Buildings.Controls.OBC.CDL.Reals.Hysteresis hys(uLow=uLowCoo, uHigh=uHighCoo)
    "Turn on pump when source temperature lower than inlet temperature"
  Buildings.Controls.OBC.CDL.Reals.Switch swi1
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant Zero(k=0) "Pump off signal"

  Buildings.Controls.OBC.CDL.Reals.Hysteresis hys1(uLow=uLowHea, uHigh=uHighHea)
    "Turn on pump when source temperature higher than inlet temperature"
  Buildings.Controls.OBC.CDL.Reals.Switch swi2
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai1(k=-1)
    "Change sign for hysteresis"

  Buildings.Controls.OBC.CDL.Reals.AddParameter Tsou_negshift(final p=-dToff,
  y(final unit="K", displayUnit="degC"))
    "Source temperature after negative shift"
  Buildings.Controls.OBC.CDL.Reals.AddParameter Tsou_posshift(final p=dToff,
  y(final unit="K", displayUnit="degC"))
    "Source temperature after positive shift"
  Buildings.Controls.OBC.CDL.Reals.Subtract dTSouSup
    "Temperature difference between source and source inlet"
  Buildings.Controls.OBC.CDL.Reals.AddParameter dTSouSupHea(final p=-dToff,
  y(final unit="K", displayUnit="degC"))
    "Temperature difference between source and source inlet corrected for heating"
  Buildings.Controls.OBC.CDL.Reals.AddParameter dTSouSupCoo(final p=dToff,
  y(final unit="K", displayUnit="degC"))
    "Temperature difference between source and source inlet corrected for cooling"

equation
  connect(NetDemBool.y, swi.u2)
  connect(TRetDis, NetDemBool.u1)
  connect(TSupDis, NetDemBool.u2)
  connect(hys.y, swi1.u2)
  connect(Zero.y, swi1.u3)
  connect(swi.y, y)
  connect(conPIDCoo.y, swi1.u1)
  connect(swi1.y, swi.u3)
  connect(hys1.y, swi2.u2)
  connect(conPIDHea.y, swi2.u1)
  connect(Zero.y, swi2.u3)
  connect(swi2.y, swi.u1)
  connect(TSou, Tsou_negshift.u)
  connect(Tsou_negshift.y, conPIDHea.u_s)
  connect(TSou, Tsou_posshift.u)
  connect(Tsou_posshift.y, conPIDCoo.u_s)
  connect(TSouOut, conPIDCoo.u_m)
  connect(TSouOut, conPIDHea.u_m)
  connect(gai1.y, hys.u)
  connect(dTSouSup.y, dTSouSupHea.u)
  connect(TSou,dTSouSup. u1)
  connect(dTSouSupHea.y, hys1.u)
  connect(dTSouSup.y,dTSouSupCoo. u)
  connect(dTSouSupCoo.y, gai1.u)
  connect(TSouIn,dTSouSup. u2)
end AgentPump1Pipe;


Main pump controller for 1 pipe networks, developed for reservoir network main circulation loop. Controller for the main circulation pump.

within Buildings.DHC.Networks.Controls;
model MainPump1Pipe
  "Main pump controller for 1 pipe networks, developed for reservoir network main circulation loop"
  parameter Integer nMix(min=1) "Number of mixing points after the substations";
  parameter Integer nSou(min=1) "Number of heat sources (and heat sinks)";
  parameter Integer nBui(min=1) "Number of heat sources (and heat sinks)";
  parameter Real yPumMin(min=0.01, max=1, final unit="1") = 0.05
    "Minimum pump speed";
  parameter Modelica.Units.SI.Temperature TMin(displayUnit="degC") = 281.15
    "Minimum loop temperature";
  parameter Modelica.Units.SI.Temperature TMax(displayUnit="degC") = 291.15
    "Maximum loop temperature";
  parameter Modelica.Units.SI.TemperatureDifference dTSlo(min=1) = 2
    "Temperature difference for slope";
  parameter Boolean use_temperatureShift = false
    "Set to false to disable temperature shift of slopes";
  parameter Boolean use_constantHeaTemShift = true
    "Set to false to disable constant temperature shift of TMax when only heating is occurring";
  parameter Modelica.Units.SI.TemperatureDifference offTMax = 2
    "TMax constant temperature shift";
  final parameter Modelica.Units.SI.TemperatureDifference delta=if
      use_temperatureShift then TMax - TMin - 3*dTSlo else 0
    "Maximum shift of slopes";
  parameter Modelica.Units.SI.TemperatureDifference dTSou_nominal[nSou](
    each min=0) = fill(4, nSou)
    "Nominal temperature difference over source";
  parameter Real k=0.01
    "Gain of controller that shifts upper and lower temperature setpoints";
  parameter Modelica.Units.SI.Time Ti(displayUnit="min") = 300
    "Time constant of integrator block that shifts upper and lower temperature setpoints";
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TMix[nMix](
    each final unit="K",
    each displayUnit="degC")
    "Temperatures at the mixing points"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TSouIn[nSou](
    each final unit="K",
    each displayUnit="degC") "Temperatures at the inlets of the sources"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TSouOut[nSou](
    each final unit="K",
    each displayUnit="degC") "Temperatures at the outlets of the sources"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput QCoo_flow[nBui](each final unit=
        "W") "Cooling power required by each building"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput y(min=0, max=1, unit="1")
    "Pump control signal"
  Buildings.Controls.OBC.CDL.Reals.MultiMin TMixMin(
    final nin=nMix,
    y(final unit="K",
      displayUnit="degC"))
    "Minimum temperature at mixing points"
  Buildings.Controls.OBC.CDL.Reals.MultiMax TMixMax(
    final nin=nMix,
    y(final unit="K", displayUnit="degC"))
    "Maximum temperature at mixing points"
  Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum(
    k=fill(1, nSou), nin=nSou)
  Buildings.Controls.OBC.CDL.Reals.Subtract dTSou[nSou]
    "Temperature differences over source"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter dTSou_nor(k=1/(
        sum(dTSou_nominal)))
    "Normalization of temperature difference over source"
  Buildings.Controls.OBC.CDL.Reals.PID conShi(
    controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    final k=k,
    Ti(displayUnit="min") = Ti,
    final yMax=1,
    final yMin=-1)
    "Controller to shift the min/max slopes"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(k=0)
    "Set point for source dT"
  Buildings.Controls.OBC.CDL.Reals.Line uppCur "Upper curve"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one(k=1) "Constant 1"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yMin(k=yPumMin)
    "Minimum pump speed"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TMax_nominal(k=TMax)
    "Maximum temperature"
  Buildings.Controls.OBC.CDL.Reals.Add TMax_upper(
    y(final unit="K", displayUnit="degC"))
    "Upper value of upper slope after shifting it"
  Buildings.Controls.OBC.CDL.Reals.Max sPos "Positive shift"
  Buildings.Controls.OBC.CDL.Reals.Min sNeg "Negative shift"
  Buildings.Controls.OBC.CDL.Reals.AddParameter TMax_lower(
    final p=-dTSlo,
    y(final unit="K", displayUnit="degC"))
    "Minimum temperatuer value of upper slope after shifting it"
  Buildings.Controls.OBC.CDL.Reals.Line lowCur "Lower curve"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TMin_nominal(k=TMin)
    "Minimum temperature"
  Buildings.Controls.OBC.CDL.Reals.Add TMin_lower(
    y(unit="K", displayUnit="degC"))
    "Lower value of lower slope after shifting it"
  Buildings.Controls.OBC.CDL.Reals.AddParameter TMin_upper(
    final p=dTSlo,
    y(final unit="K", displayUnit="degC"))
    "Maximum temperatuer value of lower slope after shifting it"
  Buildings.Controls.OBC.CDL.Reals.Max ySetPum "Change in pump signal"
  Buildings.Controls.OBC.CDL.Reals.Switch swi2
    "Switch on and off constant offset"
  Modelica.Blocks.Sources.BooleanExpression booleanExpression(y=
        use_constantHeaTemShift) "Boolean parameter to activate mode"

  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr(
    t=PpumCooThr,
    h=hysPpumCoo,
    pre_y_start=false)
    "Check pump consumption higher than zero"
  Buildings.Controls.OBC.CDL.Logical.And and2
  Buildings.Controls.OBC.CDL.Reals.MultiSum mulSum1(          k=fill(1,
        nBui), nin=nBui) "Sum of all pump consumptions"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai(final k=-delta)
    "Gain factor"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai2(final k=-delta)
    "Gain factor"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant offTMaxExp(k=offTMax)
    "Constant TMax offset"
  Buildings.Controls.OBC.CDL.Reals.Add Add(y(unit="K", displayUnit="degC"))
    "If use_heaTemShift and not use_temperatureShift use constant offset, if use_temperatureShift use PI"
  parameter Real PpumCooThr=100
    "Threshold for comparison for pump cooling power";
  parameter Real hysPpumCoo=10 "Hysteresis for cooling pump power threshold";
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gai1(final k=-1)
    "Gain factor"
equation
  connect(TMix, TMixMin.u)
  connect(TMix, TMixMax.u)
  connect(mulSum.y, dTSou_nor.u)
  connect(dTSou_nor.y, conShi.u_m)
  connect(conShi.u_s, zer.y)
  connect(uppCur.u, TMixMax.y)
  connect(uppCur.f1, yMin.y)
  connect(uppCur.f2, one.y)
  connect(TMax_nominal.y, TMax_upper.u1)
  connect(zer.y, sPos.u1)
  connect(zer.y, sNeg.u1)
  connect(conShi.y, sPos.u2)
  connect(conShi.y, sNeg.u2)
  connect(TMax_lower.u, TMax_upper.y)
  connect(uppCur.x1, TMax_lower.y)
  connect(TMax_upper.y, uppCur.x2)
  connect(TMixMin.y, lowCur.u)
  connect(TMin_nominal.y, TMin_lower.u1)
  connect(TMin_lower.y, TMin_upper.u)
  connect(TMin_upper.y, lowCur.x2)
  connect(TMin_lower.y, lowCur.x1)
  connect(lowCur.f1, one.y)
  connect(lowCur.f2, yMin.y)
  connect(uppCur.y, ySetPum.u1)
  connect(lowCur.y, ySetPum.u2)
  connect(ySetPum.y, y)
  connect(TSouOut, dTSou.u1)
  connect(TSouIn, dTSou.u2)
  connect(booleanExpression.y, and2.u2)
  connect(and2.y, swi2.u2)
  connect(dTSou.y, mulSum.u)
  connect(greThr.y, and2.u1)
  connect(QCoo_flow, mulSum1.u)
  connect(sPos.y, gai.u)
  connect(sNeg.y, gai2.u)
  connect(gai2.y, TMin_lower.u2)
  connect(swi2.y, Add.u1)
  connect(gai.y, Add.u2)
  connect(Add.y, TMax_upper.u2)
  connect(offTMaxExp.y, swi2.u3)
  connect(zer.y, swi2.u1)
  connect(mulSum1.y, gai1.u)
  connect(gai1.y, greThr.u)
end MainPump1Pipe;


within Buildings.DHC.Networks;
package Controls "Package of control blocks for distribution systems"
end Controls;


degC. This model is used to test the controller
Buildings.DHC.Networks.Controls.AgentPump.
For a practical application of the model check Buildings.DHC.Examples.Combined.SeriesVariableFlowUpdate.

within Buildings.DHC.Networks.Controls.Examples;
model AgentPump1PipeExample
    extends Modelica.Icons.Example;
    parameter Modelica.Units.SI.Temperature TSou(displayUnit="degC") = 283.15
    "Agent source temperature";
  Modelica.Blocks.Sources.CombiTimeTable TSouIn(
  table=[0,TSou; 900,TSou + 3; 2700, TSou - 3; 3600,TSou],
  extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic)
  Buildings.DHC.Networks.Controls.AgentPump1Pipe AgentPump(
    yPumMin=0,
    dToff=0.5,
    k=1,
    Ti=600)
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant  con2(k=TSou)
  Modelica.Blocks.Sources.CombiTimeTable TSouOut(
  table=[0,TSou; 900,TSou + 1; 2700, TSou - 1; 3600,TSou],
  extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic)
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TsupDis(k=TSou)
  Modelica.Blocks.Sources.CombiTimeTable TretDis(
    table=[0,TSou; 1800,TSou + 1; 1800,TSou - 1; 3600,TSou],
    smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments,
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic)
equation
  connect(con2.y, AgentPump.TSou)
  connect(TSouOut.y[1], AgentPump.TSouOut)
  connect(TSouIn.y[1], AgentPump.TSouIn)
  connect(TretDis.y[1],AgentPump.TRetDis)
  connect(TsupDis.y,AgentPump.TSupDis)
end AgentPump1PipeExample;


degC. This model is used to test the controller
Buildings.DHC.Networks.Controls.MainPump1Pipe.For a practical application of the model check Buildings.DHC.Examples.Combined.SeriesVariableFlow.

within Buildings.DHC.Networks.Controls.Examples;
model MainPump1PipeExample
    extends Modelica.Icons.Example;
    parameter Modelica.Units.SI.Temperature TSou(displayUnit="degC") = 284.65
    "Agent source temperature";
  Modelica.Blocks.Sources.CombiTimeTable TMixandTSouIn(
  table=[0,TSou; 900,TSou + 6.5; 2700,TSou - 6.5; 3600,TSou],
  extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic)
  Modelica.Blocks.Sources.CombiTimeTable TSouOut(
  table=[0,TSou; 900,TSou + 4; 2700,TSou - 4; 3600,TSou],
  extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic)
  Buildings.DHC.Networks.Controls.MainPump1Pipe conPum(
    nMix=1,
    nSou=1,
    nBui=1,
    TMax=289.15)
  Modelica.Blocks.Sources.CombiTimeTable QCoo_flow(
    table=[0,-500; 1800,-500; 1800,0; 3600,0],
    smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments,
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic)
equation
  connect(TSouOut.y, conPum.TSouOut)
  connect(TMixandTSouIn.y, conPum.TSouIn)
  connect(QCoo_flow.y, conPum.QCoo_flow)
  connect(TMixandTSouIn.y, conPum.TMix)
end MainPump1PipeExample;


District controller example models

within Buildings.DHC.Networks.Controls;
package Examples "District controller example models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within Buildings.DHC.Networks.Examples;
model Distribution1PipeExample
  "Example of distribution network with 1 pipe for Distribution1Pipe_R and Distribution1PipePlugFlow_v"
  extends Modelica.Icons.Example;
  package Medium1 = Buildings.Media.Water
    "Source side medium";
  package Medium2 = Buildings.Media.Air
    "Load side medium";
  parameter String filNam = "modelica://Buildings/Resources/Data/DHC/Loads/Examples/SwissResidential_20190916.mos"
    "File name with thermal loads as time series";
  parameter Integer nLoa=5
    "Number of served loads"
  parameter Modelica.Units.SI.Temperature T_aHeaWat_nominal = 273.15 + 40
    "Heating water inlet temperature at nominal conditions"
  parameter Modelica.Units.SI.Temperature T_bHeaWat_nominal(
    min=273.15,
    displayUnit="degC") = T_aHeaWat_nominal - 5
    "Heating water outlet temperature at nominal conditions"
  parameter Modelica.Units.SI.Temperature T_aLoaHea_nominal = 273.15 + 20
    "Load side inlet temperature at nominal conditions in heating mode"
  parameter Modelica.Units.SI.MassFlowRate mLoaHea_flow_nominal = 1
    "Load side mass flow rate at nominal conditions in heating mode"
  parameter Modelica.Units.SI.Time tau = 120
    "Time constant of fluid temperature variation at nominal flow rate"
  parameter Real facMul = 10
    "Mulitplier factor for terminal units"
  final parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal[nLoa] = terAutoSize.mHeaWat_flow_nominal*facMul
    "Nominal mass flow rate in each connection line";
  final parameter Modelica.Units.SI.MassFlowRate m_flow_nominal = sum(mCon_flow_nominal)
  "Nominal mass flow rate in the distribution line";
  final parameter Modelica.Units.SI.PressureDifference dp_nominal =
  sum(disAutoSize.con.pipDis.dp_nominal) + max(terAutoSize.dpSou_nominal)
    "Nominal pressure drop in the distribution line";
  final parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal =
      Buildings.DHC.Loads.BaseClasses.getPeakLoad(string="#Peak space heating load",
      filNam = Modelica.Utilities.Files.loadResource(filNam))/facMul
    "Design heating heat flow rate (>=0)"
  Buildings.DHC.Loads.BaseClasses.Validation.BaseClasses.FanCoil2PipeHeatingValve
    terAutoSize[nLoa](
    each final facMul=facMul,
    redeclare each final package Medium1 = Medium1,
    redeclare each final package Medium2 = Medium2,
    each final QHea_flow_nominal=QHea_flow_nominal,
    each final mLoaHea_flow_nominal=mLoaHea_flow_nominal,
    each final T_aHeaWat_nominal=T_aHeaWat_nominal,
    each final T_bHeaWat_nominal=T_bHeaWat_nominal,
    each final T_aLoaHea_nominal=T_aLoaHea_nominal) "Heating terminal unit"
  Modelica.Blocks.Sources.CombiTimeTable loa(
    tableOnFile=true,
    tableName="tab1",
    fileName=Modelica.Utilities.Files.loadResource(
      filNam),
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic,
    y(each unit="W"),
    offset={0,0,0},
    columns={2,3,4},
    smoothness=Modelica.Blocks.Types.Smoothness.MonotoneContinuousDerivative1)
    "Reader for thermal loads (y[1] is cooling load, y[2] is heating load)"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minTSet(
    k=293.15,
    y(final unit="K",
      displayUnit="degC"))
    "Minimum temperature set point"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep(
    nout=nLoa)
    "Repeat input to output an array"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep1(
    nout=nLoa)
    "Repeat input to output an array"
  Buildings.Fluid.Sources.Boundary_pT supHeaWatAutoSize(
    redeclare package Medium = Medium1,
    use_T_in=true,
    nPorts=2) "Heating water supply"
  Buildings.DHC.Networks.Distribution1Pipe_R disAutoSize(
    redeclare final package Medium = Medium1,
    nCon=nLoa,
    allowFlowReversal=false,
    mDis_flow_nominal=m_flow_nominal,
    mCon_flow_nominal=mCon_flow_nominal,
    lDis=fill(6, nLoa),
    lEnd=1)
  Buildings.Fluid.Movers.FlowControlled_dp pumAutoSize(
    redeclare package Medium = Medium1,
    per(final motorCooledByFluid=false),
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal=m_flow_nominal,
    addPowerToMedium=false,
    nominalValuesDefineDefaultPressureCurve=true,
    use_riseTime=false,
    dp_nominal=dp_nominal)
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpPum(
    k=dp_nominal)
    "Prescribed head"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSup(k=max(
        terAutoSize.T_aHeaWat_nominal)) "Supply temperature"
  Buildings.DHC.Loads.BaseClasses.Validation.BaseClasses.FanCoil2PipeHeatingValve terPlugFlow[nLoa](
    each final facMul=facMul,
    redeclare each final package Medium1 = Medium1,
    redeclare each final package Medium2 = Medium2,
    each final QHea_flow_nominal=QHea_flow_nominal,
    each final mLoaHea_flow_nominal=mLoaHea_flow_nominal,
    each final T_aHeaWat_nominal=T_aHeaWat_nominal,
    each final T_bHeaWat_nominal=T_bHeaWat_nominal,
    each final T_aLoaHea_nominal=T_aLoaHea_nominal) "Heating terminal unit"
  Buildings.DHC.Networks.Distribution1PipePlugFlow_v disPlugFlow(
    nCon=nLoa,
    redeclare final package Medium = Medium1,
    allowFlowReversal=false,
    mDis_flow_nominal=m_flow_nominal,
    mCon_flow_nominal=mCon_flow_nominal,
    lDis=fill(6, nLoa),
    lEnd=1,
    dIns=0.02,
    kIns=0.2)
  Buildings.Fluid.Movers.FlowControlled_dp pumPlugFlow(
    redeclare package Medium = Medium1,
    per(final motorCooledByFluid=false),
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal=m_flow_nominal,
    addPowerToMedium=false,
    nominalValuesDefineDefaultPressureCurve=true,
    use_riseTime=false,
    dp_nominal=dp_nominal)
  Buildings.Fluid.Sources.Boundary_pT supHeaWatPlugFlow(
    redeclare package Medium = Medium1,
    use_T_in=true,
    nPorts=2) "Heating water supply"
  Fluid.FixedResistances.BuriedPipes.PipeGroundCoupling pipeGroundCouplingSup(
    lPip=6,
    rPip=0.04,
    thiGroLay=1.1,
    nSta=5,
    nSeg=nLoa + 1)
  Buildings.DHC.ETS.BaseClasses.Pump_m_flow pumConAutoSize[nLoa](
    each dp_nominal=5000,
    redeclare final package Medium = Medium1,
    each m_flow_nominal=mLoaHea_flow_nominal) "Distribution network pump"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep2(nout=nLoa)
    "Repeat input to output an array"
  Modelica.Blocks.Sources.RealExpression mFlowConAutosize(
  y=terAutoSize[1].val.y_actual*mLoaHea_flow_nominal)
  Buildings.DHC.ETS.BaseClasses.Pump_m_flow pumConPlugFlow[nLoa](
    each dp_nominal=5000,
    redeclare final package Medium = Medium1,
    each m_flow_nominal=mLoaHea_flow_nominal) "Distribution network pump"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep3(nout=nLoa)
    "Repeat input to output an array"
  Modelica.Blocks.Sources.RealExpression mFlowConPlugFlow(
  y = terPlugFlow[1].val.y_actual*mLoaHea_flow_nominal)
protected
  parameter Medium1.ThermodynamicState sta_default=Medium1.setState_pTX(
    T=Medium1.T_default,
    p=Medium1.p_default,
    X=Medium1.X_default);
  parameter Modelica.Units.SI.Density rho_default=Medium1.density(sta_default)
    "Density, used to compute fluid volume";
equation
  connect(loa.y[2],reaRep1.u)
  connect(reaRep.y, terAutoSize.TSetHea)
  connect(reaRep1.y, terAutoSize.QReqHea_flow)
  connect(disAutoSize.ports_bCon, terAutoSize.port_aHeaWat)
  connect(pumAutoSize.port_b, disAutoSize.port_aDisSup)
  connect(THeaWatSup.y, supHeaWatAutoSize.T_in)
  connect(dpPum.y, pumAutoSize.dp_in)
  connect(reaRep.u,minTSet.y)
  connect(reaRep.y, terPlugFlow.TSetHea)
  connect(reaRep1.y, terPlugFlow.QReqHea_flow)
  connect(disPlugFlow.ports_bCon, terPlugFlow.port_aHeaWat)
  connect(pumPlugFlow.port_b, disPlugFlow.port_aDisSup)
  connect(dpPum.y, pumPlugFlow.dp_in)
  connect(THeaWatSup.y, supHeaWatPlugFlow.T_in)
  connect(pipeGroundCouplingSup.heatPorts, disPlugFlow.heatPorts)
  connect(disAutoSize.port_bDisSup, supHeaWatAutoSize.ports[1])
  connect(disPlugFlow.port_bDisSup, supHeaWatPlugFlow.ports[1])
  connect(terAutoSize.port_bHeaWat,pumConAutoSize. port_a)
  connect(pumConAutoSize.port_b, disAutoSize.ports_aCon)
  connect(mFlowConAutosize.y, reaRep2.u)
  connect(reaRep2.y, pumConAutoSize.m_flow_in)
  connect(pumConPlugFlow.port_a, terPlugFlow.port_bHeaWat)
  connect(pumConPlugFlow.port_b, disPlugFlow.ports_aCon)
  connect(pumConPlugFlow.m_flow_in, reaRep3.y)
  connect(reaRep3.u, mFlowConPlugFlow.y)
  connect(pumAutoSize.port_a, supHeaWatAutoSize.ports[2])
  connect(pumPlugFlow.port_a, supHeaWatPlugFlow.ports[2])
end Distribution1PipeExample;


within Buildings.DHC.Networks.Examples;
model Distribution2PipeExample
  "Example of distribution network with 2 pipes for Distribution2Pipe_R and Distribution2PipePlugFlow_v"
  extends Modelica.Icons.Example;
  package Medium1 = Buildings.Media.Water
    "Source side medium";
  package Medium2 = Buildings.Media.Air
    "Load side medium";
  parameter String filNam = "modelica://Buildings/Resources/Data/DHC/Loads/Examples/SwissResidential_20190916.mos"
    "File name with thermal loads as time series";
  parameter Integer nLoa = 5
    "Number of served loads"
  parameter Modelica.Units.SI.Temperature T_aHeaWat_nominal = 273.15 + 40
    "Heating water inlet temperature at nominal conditions"
  parameter Modelica.Units.SI.Temperature T_bHeaWat_nominal(
    min=273.15,
    displayUnit="degC") = T_aHeaWat_nominal - 5
    "Heating water outlet temperature at nominal conditions"
  parameter Modelica.Units.SI.Temperature T_aLoaHea_nominal = 273.15 + 20
    "Load side inlet temperature at nominal conditions in heating mode"
  parameter Modelica.Units.SI.MassFlowRate mLoaHea_flow_nominal = 1
    "Load side mass flow rate at nominal conditions in heating mode"
  parameter Modelica.Units.SI.Time tau = 120
    "Time constant of fluid temperature variation at nominal flow rate"
  parameter Real facMul = 10
    "Mulitplier factor for terminal units"
  final parameter Modelica.Units.SI.MassFlowRate mCon_flow_nominal[nLoa] =
      terAutoSize.mHeaWat_flow_nominal*facMul
    "Nominal mass flow rate in each connection line";
  final parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=sum(
      mCon_flow_nominal) "Nominal mass flow rate in the distribution line";
  final parameter Modelica.Units.SI.PressureDifference dp_nominal=sum(
      disAutoSize.con.pipDisSup.dp_nominal) + sum(disAutoSize.con.pipDisRet.dp_nominal)
       + max(terAutoSize.dpSou_nominal)
    "Nominal pressure drop in the distribution line";
  final parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal=
      Buildings.DHC.Loads.BaseClasses.getPeakLoad(string="#Peak space heating load",
      filNam = Modelica.Utilities.Files.loadResource(filNam))/facMul
    "Design heating heat flow rate (>=0)"
  Buildings.DHC.Loads.BaseClasses.Validation.BaseClasses.FanCoil2PipeHeatingValve
    terAutoSize[nLoa](
    each final facMul=facMul,
    redeclare each final package Medium1 = Medium1,
    redeclare each final package Medium2 = Medium2,
    each final QHea_flow_nominal=QHea_flow_nominal,
    each final mLoaHea_flow_nominal=mLoaHea_flow_nominal,
    each final T_aHeaWat_nominal=T_aHeaWat_nominal,
    each final T_bHeaWat_nominal=T_bHeaWat_nominal,
    each final T_aLoaHea_nominal=T_aLoaHea_nominal) "Heating terminal unit"
  Modelica.Blocks.Sources.CombiTimeTable loa(
    tableOnFile=true,
    tableName="tab1",
    fileName=Modelica.Utilities.Files.loadResource(
      filNam),
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic,
    y(each unit="W"),
    offset={0,0,0},
    columns={2,3,4},
    smoothness=Modelica.Blocks.Types.Smoothness.MonotoneContinuousDerivative1)
    "Reader for thermal loads (y[1] is cooling load, y[2] is heating load)"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant minTSet(
    k=293.15,
    y(final unit="K",
      displayUnit="degC"))
    "Minimum temperature set point"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep(
    nout=nLoa)
    "Repeat input to output an array"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator reaRep1(
    nout=nLoa)
    "Repeat input to output an array"
  Buildings.Fluid.Sources.Boundary_pT supHeaWatAutoSize(
    redeclare package Medium = Medium1,
    use_T_in=true,
    nPorts=2) "Heating water supply"
  Buildings.DHC.Networks.Distribution2Pipe_R disAutoSize(
    redeclare final package Medium = Medium1,
    nCon=nLoa,
    allowFlowReversal=false,
    mDis_flow_nominal=m_flow_nominal,
    mCon_flow_nominal=mCon_flow_nominal,
    mEnd_flow_nominal=m_flow_nominal,
    lDis=fill(6, nLoa),
    lEnd=1)
  Buildings.Fluid.Movers.FlowControlled_dp pumAutoSize(
    redeclare package Medium = Medium1,
    per(final motorCooledByFluid=false),
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal=m_flow_nominal,
    addPowerToMedium=false,
    nominalValuesDefineDefaultPressureCurve=true,
    use_riseTime=false,
    dp_nominal=dp_nominal)
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dpPum(
    k=dp_nominal)
    "Prescribed head"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant THeaWatSup(
  k=max(terAutoSize.T_aHeaWat_nominal)) "Supply temperature"
  Buildings.DHC.Loads.BaseClasses.Validation.BaseClasses.FanCoil2PipeHeatingValve terPlugFlow[nLoa](
    each final facMul=facMul,
    redeclare each final package Medium1 = Medium1,
    redeclare each final package Medium2 = Medium2,
    each final QHea_flow_nominal=QHea_flow_nominal,
    each final mLoaHea_flow_nominal=mLoaHea_flow_nominal,
    each final T_aHeaWat_nominal=T_aHeaWat_nominal,
    each final T_bHeaWat_nominal=T_bHeaWat_nominal,
    each final T_aLoaHea_nominal=T_aLoaHea_nominal) "Heating terminal unit"
  Buildings.DHC.Networks.Distribution2PipePlugFlow_v disPlugFlow(
    nCon=nLoa,
    redeclare final package Medium = Medium1,
    allowFlowReversal=false,
    mDis_flow_nominal=m_flow_nominal,
    mCon_flow_nominal=mCon_flow_nominal,
    mEnd_flow_nominal=m_flow_nominal,
    lDis=fill(6, nLoa),
    lEnd=1)
  Buildings.Fluid.Movers.FlowControlled_dp pumPlugFlow(
    redeclare package Medium = Medium1,
    per(final motorCooledByFluid=false),
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal=m_flow_nominal,
    addPowerToMedium=false,
    nominalValuesDefineDefaultPressureCurve=true,
    use_riseTime=false,
    dp_nominal=dp_nominal)
  Buildings.Fluid.Sources.Boundary_pT supHeaWatPlugFlow(
    redeclare package Medium = Medium1,
    use_T_in=true,
    nPorts=2) "Heating water supply"
  Fluid.FixedResistances.BuriedPipes.PipeGroundCoupling pipeGroundCouplingRet(
    lPip=6,
    rPip=0.04,
    thiGroLay=1.1,
    nSta=5,
    nSeg=nLoa)
  Fluid.FixedResistances.BuriedPipes.PipeGroundCoupling pipeGroundCouplingSup(
    lPip=6,
    rPip=0.04,
    thiGroLay=1.1,
    nSta=5,
    nSeg=nLoa + 1)
protected
  parameter Medium1.ThermodynamicState sta_default=Medium1.setState_pTX(
    T=Medium1.T_default,
    p=Medium1.p_default,
    X=Medium1.X_default);
  parameter Modelica.Units.SI.Density rho_default=Medium1.density(sta_default)
    "Density, used to compute fluid volume";
equation
  connect(loa.y[2],reaRep1.u)
  connect(reaRep.y, terAutoSize.TSetHea)
  connect(reaRep1.y, terAutoSize.QReqHea_flow)
  connect(terAutoSize.port_bHeaWat, disAutoSize.ports_aCon)
  connect(disAutoSize.ports_bCon, terAutoSize.port_aHeaWat)
  connect(pumAutoSize.port_b, disAutoSize.port_aDisSup)
  connect(THeaWatSup.y, supHeaWatAutoSize.T_in)
  connect(dpPum.y, pumAutoSize.dp_in)
  connect(reaRep.u,minTSet.y)
  connect(reaRep.y, terPlugFlow.TSetHea)
  connect(reaRep1.y, terPlugFlow.QReqHea_flow)
  connect(terPlugFlow.port_bHeaWat, disPlugFlow.ports_aCon)
  connect(disPlugFlow.ports_bCon, terPlugFlow.port_aHeaWat)
  connect(pumPlugFlow.port_b, disPlugFlow.port_aDisSup)
  connect(dpPum.y, pumPlugFlow.dp_in)
  connect(THeaWatSup.y, supHeaWatPlugFlow.T_in)
  connect(disAutoSize.port_bDisRet, supHeaWatAutoSize.ports[1])
  connect(disPlugFlow.port_bDisRet, supHeaWatPlugFlow.ports[1])
  connect(pipeGroundCouplingRet.heatPorts, disPlugFlow.heatPortsRet)
  connect(pipeGroundCouplingSup.heatPorts, disPlugFlow.heatPortsDis)
  connect(supHeaWatAutoSize.ports[2], pumAutoSize.port_a)
  connect(supHeaWatPlugFlow.ports[2], pumPlugFlow.port_a)
end Distribution2PipeExample;


This package contains example models

within Buildings.DHC.Networks;
package Examples "This package contains example models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within Buildings.DHC.Networks;
package Pipes "Package containing pipe models used within district network modeling"
  extends Modelica.Icons.VariantsPackage;
end Pipes;


Pipe model parameterized with pressure drop per pipe length. This model is similar to

Buildings.Fluid.FixedResistances.HydraulicDiameter
except for the modifications below which allow to use this model for computing the
hydraulic diameter at initialization, based on the pressure drop per pipe length
at nominal flow rate.

within Buildings.DHC.Networks.Pipes;
model PipeAutosize "Pipe model parameterized with pressure drop per pipe length"
  extends Buildings.Fluid.FixedResistances.PressureDrop(
    final deltaM = eta_default*dh/4*Modelica.Constants.pi*ReC/m_flow_nominal_pos,
    final dp_nominal = dp_length_nominal*length);

  parameter Modelica.Units.SI.Length dh(
    fixed=false,
    start=0.01,
    min=0.001) "Hydraulic diameter (assuming a round cross section area)";

  parameter Real dp_length_nominal(final unit="Pa/m") = 250
    "Pressure drop per pipe length at nominal flow rate";

  parameter Modelica.Units.SI.Length length "Length of the pipe";

  parameter Real ReC(min=0) = 4000
    "Reynolds number where transition to turbulence starts";
  parameter Modelica.Units.SI.Length roughness(min=0) = 2.5e-5
    "Absolute roughness of pipe, with a default for a smooth steel pipe (PE100: 7E-6)";

  parameter Real fac(min=1) = 2
    "Factor to take into account resistance of bends etc., fac=dp_nominal/dpStraightPipe_nominal";

  final parameter Modelica.Units.SI.PressureDifference dpStraightPipe_nominal(
      displayUnit="Pa")=Modelica.Fluid.Pipes.BaseClasses.WallFriction.Detailed.pressureLoss_m_flow(
    m_flow=m_flow_nominal,
    rho_a=rho_default,
    rho_b=rho_default,
    mu_a=mu_default,
    mu_b=mu_default,
    length=length,
    diameter=dh,
    roughness=roughness,
    m_flow_small=m_flow_small)
    "Pressure loss of a straight pipe at m_flow_nominal";

  Modelica.Units.SI.Velocity v = m_flow/(rho_default*ARound)
    "Flow velocity (assuming a round cross section area)";

protected
  parameter Modelica.Units.SI.Area ARound = dh^2*Modelica.Constants.pi/4
    "Cross sectional area (assuming a round cross section area)";

  parameter Modelica.Units.SI.Velocity v_nominal = m_flow_nominal/(rho_default*
      ARound)
    "Velocity at m_flow_nominal (used to compute default value for hydraulic diameter dh)";

  parameter Medium.ThermodynamicState state_default= Medium.setState_pTX(
      T=Medium.T_default,
      p=Medium.p_default,
      X=Medium.X_default[1:Medium.nXi]) "Default state";

  parameter Modelica.Units.SI.Density rho_default=Medium.density(state_default)
    "Density at nominal condition";

  parameter Modelica.Units.SI.DynamicViscosity mu_default = Medium.dynamicViscosity(state_default)
    "Dynamic viscosity at nominal condition";
initial equation
  dp_nominal = fac*dpStraightPipe_nominal;
end PipeAutosize;


Pipe model parameterized with hydraulic diameter. This model is similar to

Buildings.Fluid.FixedResistances.HydraulicDiameter
except that a binding equation is provided to compute the nominal fluid velocity
from the hydraulic diameter (as opposed to the hydraulic diameter being
computed from the nominal fluid velocity in the original model).

within Buildings.DHC.Networks.Pipes;
model PipeStandard "Pipe model parameterized with hydraulic diameter"
  extends Buildings.Fluid.FixedResistances.HydraulicDiameter(
    dp(nominal = 1E5),
    final linearized = false,
    final v_nominal = m_flow_nominal*4/(rho_default * dh^2 * Modelica.Constants.pi));
end PipeStandard;


Validation models for Pipes

within Buildings.DHC.Networks.Pipes;
package Validation "Validation models for Pipes"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


within Buildings.DHC.Networks.Pipes.Validation;
model Pipe "Validates the PipeAutosize model initialization"
  extends Modelica.Icons.Example;
  package Medium = Buildings.Media.Water "Medium model";
  parameter Real dp1_length_nominal(final unit="Pa/m") = 1000 "Pressure drop per unit length 1";
  parameter Real dp2_length_nominal(final unit="Pa/m") = 0.1 "Pressure drop per unit length 2";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal = 0.01 "Nominal mass flow rate 1";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal = 1000 "Nominal mass flow rate 2";
  Buildings.Fluid.Sources.Boundary_pT sin(redeclare final package Medium = Medium,
   nPorts=4) "Sink for water flow"
  Buildings.DHC.Networks.Pipes.PipeStandard pipSta1(
    redeclare final package Medium = Medium,
    m_flow_nominal=m1_flow_nominal,
    dh=0.00548,
    length=100) "Pipe 1 with standard hydraulic diameter"
  Buildings.Fluid.Sources.MassFlowSource_T souSta1(
    redeclare final package Medium = Medium,
    m_flow=m1_flow_nominal,
    nPorts=1) "Source of water flow for standard pipe 1"
  Buildings.Fluid.Sources.MassFlowSource_T souAut2(
    redeclare final package Medium = Medium,
    m_flow=m2_flow_nominal,
    nPorts=1) "Source of water flow for autosized pipe 2"
  Buildings.DHC.Networks.Pipes.PipeAutosize pipAut2(
    redeclare final package Medium = Medium,
    m_flow_nominal=m2_flow_nominal,
    dp_length_nominal=dp2_length_nominal,
    length=100) "Pipe 2 with autosized hydraulic diameter"
  Fluid.Sources.MassFlowSource_T souAut1(
    redeclare final package Medium = Medium,
    m_flow=m1_flow_nominal,
    nPorts=1) "Source of water flow for autosized pipe 1"
  Pipes.PipeAutosize pipAut1(
    redeclare final package Medium = Medium,
    m_flow_nominal=m1_flow_nominal,
    dp_length_nominal=dp1_length_nominal,
    length=100) "Pipe 1 with autosized hydraulic diameter"
  Pipes.PipeStandard pipSta2(
    redeclare final package Medium = Medium,
    m_flow_nominal=m2_flow_nominal,
    dh=2.943,
    length=100) "Pipe 2 with standard hydraulic diameter"
  Fluid.Sources.MassFlowSource_T souSta2(
    redeclare final package Medium = Medium,
    m_flow=m2_flow_nominal,
    nPorts=1) "Source of water flow for standard pipe 2"
equation
  connect(souSta1.ports[1], pipSta1.port_a)
  connect(souAut2.ports[1], pipAut2.port_a)
  connect(souAut1.ports[1], pipAut1.port_a)
  connect(souSta2.ports[1], pipSta2.port_a)
  connect(pipAut1.port_b, sin.ports[1])
  connect(pipAut2.port_b, sin.ports[2])
  connect(pipSta1.port_b, sin.ports[3])
  connect(pipSta2.port_b, sin.ports[4])
end Pipe;


within Buildings.DHC.Networks.Steam;
model ConnectionCondensatePipe
  "Connection for a steam district heating network featuring the condensate return pipe"
  extends
    Buildings.DHC.Networks.BaseClasses.PartialConnection2Pipe2Medium(
    redeclare final model Model_pipDisRet =
        Buildings.Fluid.FixedResistances.PressureDrop (
          final dp_nominal=dp_nominal),
    redeclare model Model_pipDisSup =
        Buildings.Fluid.FixedResistances.LosslessPipe);
  parameter Modelica.Units.SI.PressureDifference dp_nominal(displayUnit="Pa")
    "Pressure drop at nominal mass flow rate"
  Buildings.Fluid.FixedResistances.PressureDrop pipConRet(
    redeclare package Medium = MediumRet,
    m_flow_nominal=mCon_flow_nominal,
    final dp_nominal=dp_nominal)
    "Connection return pipe"
equation
  connect(port_aCon, pipConRet.port_a)
  connect(pipConRet.port_b, junConRet.port_3)
  connect(port_bCon, junConSup.port_3)
  connect(pipDisSup.port_b, junConSup.port_1)
  connect(pipDisRet.port_a, junConRet.port_2)
end ConnectionCondensatePipe;


Model of a steam distribution network using fixed resistance pipe model for condensate returns. This is a model of a distribution network for steam heating systems.
The model utilizes a split-medium approach with two separate medium
declarations between liquid (condensate return) and vapor (steam
supply) states. The piping network features:

within Buildings.DHC.Networks.Steam;
model DistributionCondensatePipe
  "Model of a steam distribution network using fixed resistance pipe model for condensate returns"
  extends Buildings.DHC.Networks.BaseClasses.PartialDistribution2Pipe2Medium(
    redeclare ConnectionCondensatePipe con[nCon](
      each final dp_nominal=dp_nominal),
    redeclare model Model_pipDis=Buildings.Fluid.FixedResistances.LosslessPipe);
  parameter Modelica.Units.SI.PressureDifference dp_nominal(displayUnit="Pa")
    "Pressure drop at nominal mass flow rate"
end DistributionCondensatePipe;


within Buildings.DHC.Networks;
package Steam "Collection of models for distribution networks involving steam"
  extends Modelica.Icons.VariantsPackage;
end Steam;


within Buildings.DHC.Networks.Steam.Examples;
model ConnectionCondensatePipe "Example model for the steam heating connection block"
  extends Modelica.Icons.Example;

  package MediumSte = Buildings.Media.Steam "Steam medium";
  package MediumWat =
      Buildings.Media.Specialized.Water.TemperatureDependentDensity
    "Water medium";

  parameter Modelica.Units.SI.AbsolutePressure pSat = 150000
    "Saturation pressure";
  parameter Modelica.Units.SI.Temperature TSat = MediumSte.saturationTemperature(pSat)
     "Saturation temperature";
  parameter Modelica.Units.SI.SpecificEnthalpy dh_nominal = MediumSte.specificEnthalpy(
  MediumSte.setState_pTX(p=pSat,T=TSat,X=MediumSte.X_default)) -
  MediumWat.specificEnthalpy(MediumWat.setState_pTX(p=pSat,T=TSat,X=MediumWat.X_default))
    "Nominal change in enthalpy due to vaporization";
  parameter Modelica.Units.SI.Power Q_flow_nominal = 200E3
    "Nominal heat flow rate";
  parameter Real QHeaLoa[:, :] = [0, 200E3; 6, 200E3; 6, 50E3; 18, 50E3; 18, 75E3; 24, 75E3]
    "Heating load profile for the building";
  parameter Modelica.Units.SI.PressureDifference dp_nominal = 6000
    "Pressure drop at nominal mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal = Q_flow_nominal/dh_nominal
    "Nominal mass flow rate";

  Modelica.Blocks.Sources.Ramp ram(duration=60, startTime=60) "Ramp signal"
  Fluid.Sources.MassFlowSource_T souWat(
    redeclare package Medium = MediumWat,
    use_m_flow_in=true,
    nPorts=1)
    "Water source"
  Fluid.Sources.MassFlowSource_T souSte(
    redeclare package Medium = MediumSte,
    use_m_flow_in=true,
    nPorts=1)
    "Steam source"
  Buildings.Fluid.Sources.Boundary_pT sinWat(
    redeclare package Medium = MediumWat,
    p(displayUnit="Pa") = 101325,
    nPorts=1)
    "Water condensate sink"
  Fluid.Sources.Boundary_pT sinSte(
    redeclare package Medium = MediumSte,
    p=pSat,
    T=TSat,
    nPorts=1)
    "Steam sink"
  Buildings.DHC.Networks.Steam.ConnectionCondensatePipe con(
    redeclare package MediumSup = MediumSte,
    redeclare package MediumRet = MediumWat,
    mDis_flow_nominal=m_flow_nominal,
    mCon_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    dp_nominal=1500)
    "Connection block for steam systems"

equation
  connect(con.port_bDisRet, sinWat.ports[1])
  connect(con.port_bCon, sinSte.ports[1])
  connect(souSte.ports[1], con.port_aDisSup)
  connect(souWat.ports[1], con.port_aCon)
  connect(ram.y, souSte.m_flow_in)
  connect(ram.y, souWat.m_flow_in)
end ConnectionCondensatePipe;


within Buildings.DHC.Networks.Steam.Examples;
model DistributionCondensatePipe
  "Example model for the steam heating distribution network"
  extends Modelica.Icons.Example;

  package MediumSte = Buildings.Media.Steam "Steam medium";
  package MediumWat =
      Buildings.Media.Specialized.Water.TemperatureDependentDensity
    "Water medium";

  parameter Modelica.Units.SI.AbsolutePressure pSat = 150000
    "Saturation pressure";
  parameter Modelica.Units.SI.Temperature TSat = MediumSte.saturationTemperature(pSat)
     "Saturation temperature";
  parameter Modelica.Units.SI.SpecificEnthalpy dh_nominal = MediumSte.specificEnthalpy(
  MediumSte.setState_pTX(p=pSat,T=TSat,X=MediumSte.X_default)) -
  MediumWat.specificEnthalpy(MediumWat.setState_pTX(p=pSat,T=TSat,X=MediumWat.X_default))
    "Nominal change in enthalpy due to vaporization";
  parameter Modelica.Units.SI.Power Q1_flow_nominal=200E3
    "Nominal heat flow rate, building 1";
  parameter Modelica.Units.SI.Power Q2_flow_nominal=300E3
    "Nominal heat flow rate, building 2";
  parameter Real QHeaLoa1[:, :]= [0, 200E3; 6, 200E3; 6, 50E3; 18, 50E3; 18, 75E3; 24, 75E3]
    "Heating load profile for the building 1";
  parameter Real QHeaLoa2[:, :]= [0, 100E3; 6, 200E3; 6, 200E3; 10, 300E3; 18, 300E3; 24, 100E3]
    "Heating load profile for the building 2";
  parameter Modelica.Units.SI.PressureDifference dp_nominal=6000
    "Pressure drop at nominal mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal=
    Q1_flow_nominal/dh_nominal
    "Nominal mass flow rate, building 1";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal=
    Q2_flow_nominal/dh_nominal
    "Nominal mass flow rate, building 2";

  Buildings.Fluid.Sources.Boundary_pT souSte(
    redeclare package Medium = MediumSte,
    p=pSat,
    T=TSat,
    nPorts=1)
    "Steam source"
  Buildings.Fluid.Sources.Boundary_pT sinWat(
    redeclare package Medium = MediumWat,
    p(displayUnit="Pa") = 101325,
    nPorts=1)
    "Water condensate sink"
  Buildings.DHC.Networks.Steam.DistributionCondensatePipe dis(
    redeclare package MediumSup = MediumSte,
    redeclare package MediumRet = MediumWat,
    nCon=2,
    mDis_flow_nominal=m1_flow_nominal + m2_flow_nominal,
    mCon_flow_nominal={m1_flow_nominal,m2_flow_nominal},
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    dp_nominal=dp_nominal)
  Buildings.DHC.Loads.Steam.BuildingTimeSeriesAtETS bui[2](
    redeclare package MediumSte = MediumSte,
    redeclare package MediumWat = MediumWat,
    each pSte_nominal=pSat,
    each TSte_nominal=TSat,
    each dh_nominal=dh_nominal,
    Q_flow_nominal={Q1_flow_nominal,Q2_flow_nominal},
    each dp_nominal=dp_nominal,
    each energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    QHeaLoa={QHeaLoa1,QHeaLoa2},
    each timeScale(displayUnit="s") = 3600)
    "Building vector consisting of 2 buildings"

equation
  connect(souSte.ports[1], dis.port_aDisSup)
  connect(sinWat.ports[1], dis.port_bDisRet)
  connect(dis.ports_bCon, bui.port_a)
  connect(bui.port_b, dis.ports_aCon)
end DistributionCondensatePipe;


within Buildings.DHC.Networks.Steam;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Package of models for central plants

within Buildings.DHC;
package Plants "Package of models for central plants"
  extends Modelica.Icons.VariantsPackage;
end Plants;


Package with base classes

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


Partial class for modeling a plant

within Buildings.DHC.Plants.BaseClasses;
partial model PartialPlant
  "Partial class for modeling a plant"
  replaceable package Medium=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Service side medium";
  replaceable package MediumHea_b=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Service side medium at heating supply"
  parameter Buildings.DHC.Types.DistrictSystemType
  typ=Buildings.DHC.Types.DistrictSystemType.CombinedGeneration2to4
    "Type of district system"
  parameter Boolean have_fan=false
    "Set to true if fan power is computed"
  parameter Boolean have_pum=false
    "Set to true if pump power is computed"
  parameter Boolean have_eleHea=false
    "Set to true if the plant has electric heating system"
  parameter Integer nFue=0
    "Number of fuel types (0 means no combustion system)"
  final parameter Boolean have_fue=nFue>0
    "Set to true if the plant has fuel use";
  parameter Boolean have_eleCoo=false
    "Set to true if the plant has electric cooling system"
  parameter Boolean have_weaBus=false
    "Set to true to use a weather bus"
  parameter Boolean allowFlowReversal=false
    "Set to true to allow flow reversal in service lines"
  parameter Buildings.Fluid.Data.Fuels.Generic fue[nFue]
    "Fuel type"
  // IO CONNECTORS
  Modelica.Fluid.Interfaces.FluidPort_a port_aSerAmb(
    redeclare package Medium = Medium,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=Medium.h_default, nominal=Medium.h_default))
 if have_serAmb
    "Fluid connector for ambient water service supply line"
  Modelica.Fluid.Interfaces.FluidPort_b port_bSerAmb(
    redeclare package Medium = Medium,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=Medium.h_default, nominal=Medium.h_default))
 if have_serAmb
    "Fluid connector for ambient water service return line"
  Modelica.Fluid.Interfaces.FluidPort_a port_aSerHea(
    redeclare package Medium = Medium,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=Medium.h_default, nominal=Medium.h_default)) if have_hea
    "Fluid connector for heating service supply line"
  Modelica.Fluid.Interfaces.FluidPort_b port_bSerHea(
    redeclare package Medium = MediumHea_b,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumHea_b.h_default, nominal=MediumHea_b.h_default)) if have_hea
    "Fluid connector for heating service return line"
  Modelica.Fluid.Interfaces.FluidPort_a port_aSerCoo(
    redeclare package Medium = Medium,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=Medium.h_default, nominal=Medium.h_default))
 if have_coo
    "Fluid connector for cooling service supply line"
  Modelica.Fluid.Interfaces.FluidPort_b port_bSerCoo(
    redeclare package Medium = Medium,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=Medium.h_default, nominal=Medium.h_default))
 if have_coo
    "Fluid connector for cooling service return line"
  Buildings.BoundaryConditions.WeatherData.Bus weaBus if have_weaBus
    "Weather data bus"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput PHea(
    final unit="W") if have_eleHea
    "Power drawn by heating system"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput PCoo(
    final unit="W") if have_eleCoo
    "Power drawn by cooling system"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput PFan(
    final unit="W") if have_fan
    "Power drawn by fan motors"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput PPum(
    final unit="W") if have_pum
    "Power drawn by pump motors"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput QFue_flow(
    final unit="W") if have_fue
    "Fuel energy input rate"
protected
  final parameter Boolean have_hea=typ <> Buildings.DHC.Types.DistrictSystemType.Cooling and
  typ <> Buildings.DHC.Types.DistrictSystemType.CombinedGeneration5
  "Boolean flag to enable fluid connectors for heating service line";
  final parameter Boolean have_coo=typ == Buildings.DHC.Types.DistrictSystemType.CombinedGeneration1 or
  typ == Buildings.DHC.Types.DistrictSystemType.CombinedGeneration2to4 or
  typ == Buildings.DHC.Types.DistrictSystemType.Cooling
  "Boolean flag to enable fluid connectors for cooling service line";
  final parameter Boolean have_serAmb=typ == Buildings.DHC.Types.DistrictSystemType.CombinedGeneration5
  "Boolean flag to enable fluid connector for ambient water service line";
end PartialPlant;