within AixLib.Fluid.FixedResistances.Examples;
model FlowJunction
  "Test model for the three way splitter/mixer model"
  extends Modelica.Icons.Example;

 package Medium = AixLib.Media.Air "Medium model";

  AixLib.Fluid.FixedResistances.Junction spl(
    redeclare package Medium = Medium,
    m_flow_nominal={1,2,3},
    dp_nominal={5,10,15},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial) "Splitter"

  AixLib.Fluid.Sources.Boundary_pT bou1(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    use_p_in=true,
    nPorts=1)
    "Pressure boundary condition"

  AixLib.Fluid.Sources.Boundary_pT bou2(
    redeclare package Medium = Medium,
    T=273.15 + 20,
    p(displayUnit="Pa") = 101325,
    nPorts=1)
    "Pressure boundary condition"

  AixLib.Fluid.Sources.Boundary_pT bou3(
    redeclare package Medium = Medium,
    T=273.15 + 30,
    use_p_in=true,
    nPorts=1)
    "Pressure boundary condition"

    Modelica.Blocks.Sources.Ramp P1(
    offset=101320,
    height=10,
    duration=20,
    startTime=20)
    "Ramp pressure signal"

    Modelica.Blocks.Sources.Ramp P3(
      offset=101320,
      height=10,
      duration=20,
      startTime=70)
    "Ramp pressure signal"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTem1(
    redeclare package Medium = Medium,
    m_flow_nominal=1)
    "Temperature sensor"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTem2(
    redeclare package Medium = Medium,
    m_flow_nominal=2)
    "Temperature sensor"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTem3(
    redeclare package Medium = Medium,
    m_flow_nominal=3)
    "Temperature sensor"

equation
  connect(P1.y, bou1.p_in)
  connect(bou3.p_in, P3.y)
  connect(bou3.ports[1], senTem3.port_a)
  connect(senTem3.port_b, spl.port_3)
  connect(bou1.ports[1], senTem1.port_a)
  connect(senTem1.port_b, spl.port_1)
  connect(spl.port_2, senTem2.port_a)
  connect(senTem2.port_b, bou2.ports[1])
end FlowJunction;


Medium in the system

within AixLib.Fluid.FixedResistances.Examples;
model GenericPipe

  extends Modelica.Icons.Example;

   replaceable package Medium =
      Modelica.Media.Water.ConstantPropertyLiquidWater "Medium in the system"

  Modelica.Fluid.Sources.MassFlowSource_T Source(
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    use_T_in=true,
    m_flow=0.1,
    T=323.15,
    nPorts=1)
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature fixedTemp(each T=
        278.15)
  Modelica.Fluid.Sources.FixedBoundary
                                  Sink(
    redeclare package Medium = Medium, nPorts=1)
  inner Modelica.Fluid.System system
  Sensors.TemperatureTwoPort              senTemIn(
    redeclare package Medium = Medium,
    m_flow_nominal=0.001,
    T_start=323.15) "Temperature sensor"
  Sensors.TemperatureTwoPort              senTemOut(
    redeclare package Medium = Medium,
    m_flow_nominal=0.001,
    T_start=323.15) "Temperature sensor"
  Modelica.Blocks.Sources.Ramp Tin(
    height=20,
    duration=0,
    offset=273.15 + 50,
    startTime=300) "Ramp pressure signal"
  AixLib.Fluid.FixedResistances.GenericPipe genericPipe(
    redeclare package Medium = Medium,
    pipeModel="SimplePipe",
    length=10,
    withInsulation=true,
    withConvection=true,
    T_start=323.15,
    m_flow_nominal=0.3,
    parameterPipe=DataBase.Pipes.Copper.Copper_28x1(),
    parameterIso=DataBase.Pipes.Insulation.Iso50pc(),
    nNodes=3,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
equation
  connect(Source.ports[1], senTemIn.port_a)
  connect(senTemOut.port_b, Sink.ports[1])
  connect(Tin.y, Source.T_in)
  connect(senTemIn.port_b, genericPipe.port_a)
  connect(genericPipe.port_b, senTemOut.port_a)
  connect(fixedTemp.port, genericPipe.heatPort)
end GenericPipe;


within AixLib.Fluid.FixedResistances.Examples;
model HydraulicDiameter
  "Example model for flow resistance with hydraulic diameter as parameter"
  extends Modelica.Icons.Example;

 package Medium = AixLib.Media.Water "Medium model";

  Modelica.Blocks.Sources.Ramp P(
    duration=1,
    height=4000,
    offset=300000 - 2000)
     "Ramp pressure signal"

  AixLib.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    T=273.15 + 20,
    use_p_in=true,
    nPorts=2)
    "Pressure boundary condition"

  AixLib.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=2,
    p(displayUnit="Pa") = 300000)
    "Pressure boundary condition"

  AixLib.Fluid.FixedResistances.HydraulicDiameter res(
    redeclare package Medium = Medium,
    m_flow_nominal=0.2,
    v_nominal=1,
    from_dp=true,
    length=1)
    "Fixed resistance with specified hydraulic diameter"

  AixLib.Fluid.FixedResistances.HydraulicDiameter resLarPip(
    redeclare package Medium = Medium,
    from_dp=true,
    m_flow_nominal=10,
    length=100)
    "Fixed resistance with specified hydraulic diameter of a large pipe"
equation
  connect(P.y, sou.p_in)
  connect(sou.ports[1], res.port_a)
  connect(res.port_b, sin.ports[1])
  connect(resLarPip.port_a, sou.ports[2])
  connect(resLarPip.port_b, sin.ports[2])
end HydraulicDiameter;


within AixLib.Fluid.FixedResistances;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Medium in the system

within AixLib.Fluid.FixedResistances.Examples;
model Pipe

  extends Modelica.Icons.Example;

   replaceable package Medium =
      Modelica.Media.Water.ConstantPropertyLiquidWater "Medium in the system"

  Modelica.Fluid.Sources.MassFlowSource_T Source(
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    use_T_in=true,
    m_flow=0.001,
    T=323.15,
    nPorts=1)
  Modelica.Blocks.Sources.Ramp ramp(
    duration=3600,
    offset=273.15 + 40,
    startTime=400,
    height=40)
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature fixedTemp(T=293.15)
  Modelica.Fluid.Sources.FixedBoundary
                                  Sink(
    redeclare package Medium = Medium, nPorts=1)
  inner Modelica.Fluid.System system
  Modelica.Fluid.Sensors.Temperature temperatureAfter(redeclare package Medium =
        Medium)
  Modelica.Fluid.Sensors.Temperature temperatureBefore(redeclare package Medium =
        Medium)
  AixLib.Fluid.FixedResistances.Pipe dynamicPipeEBCAggregated_Ambient_Loss_UC(
    length=2,
    redeclare package Medium = Medium,
    parameterPipe=DataBase.Pipes.Copper.Copper_6x1(),
    parameterIso=DataBase.Pipes.Insulation.Iso100pc(),
    diameter=dynamicPipeEBCAggregated_Ambient_Loss_UC.parameterPipe.d_i,
    nNodes=5,
    Heat_Loss_To_Ambient=true,
    isEmbedded=false,
    withInsulation=true,
    use_HeatTransferConvective=true)
equation
  connect(ramp.y, Source.T_in)
  connect(dynamicPipeEBCAggregated_Ambient_Loss_UC.Star, fixedTemp.port)
  connect(Source.ports[1], dynamicPipeEBCAggregated_Ambient_Loss_UC.port_a)
  connect(temperatureBefore.port, dynamicPipeEBCAggregated_Ambient_Loss_UC.port_a)
  connect(dynamicPipeEBCAggregated_Ambient_Loss_UC.port_b, Sink.ports[1])
  connect(temperatureAfter.port, dynamicPipeEBCAggregated_Ambient_Loss_UC.port_b)
  connect(fixedTemp.port, dynamicPipeEBCAggregated_Ambient_Loss_UC.heatPort_outside)
end Pipe;


Simple example of plug flow pipe

within AixLib.Fluid.FixedResistances.Examples;
model PlugFlowPipe "Simple example of plug flow pipe"
  extends Modelica.Icons.Example;
  replaceable package Medium = AixLib.Media.Water "Medium in the pipe"

  final parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=3
    "Mass flow rate";

  Modelica.Blocks.Sources.Ramp Tin(
    height=20,
    duration=0,
    offset=273.15 + 50,
    startTime=100) "Ramp pressure signal"
  Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=2,
    p(displayUnit="Pa") = 101325) "Pressure boundary condition"
  AixLib.Fluid.FixedResistances.PlugFlowPipe pip(
    redeclare package Medium = Medium,
    dh=0.1,
    length=100,
    dIns=0.05,
    kIns=0.028,
    m_flow_nominal=m_flow_nominal,
    cPip=500,
    thickness=0.0032,
    initDelay=true,
    m_flow_start=m_flow_nominal,
    rhoPip=8000,
    T_start_in=323.15,
    T_start_out=323.15) "Pipe"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature bou[2](each T=283.15)
    "Boundary temperature"
  AixLib.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    use_T_in=true,
    m_flow=m_flow_nominal,
    nPorts=1) "Flow source"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTemOut(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    tau=0,
    T_start=323.15) "Temperature sensor"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTemIn(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    tau=0,
    T_start=323.15) "Temperature sensor"
  Sensors.TemperatureTwoPort senTemInNoMix(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    tau=0,
    T_start=323.15) "Temperature sensor"
  AixLib.Fluid.FixedResistances.PlugFlowPipe pipNoMix(
    have_pipCap=false,
    redeclare package Medium = Medium,
    dh=0.1,
    length=100,
    dIns=0.05,
    kIns=0.028,
    m_flow_nominal=m_flow_nominal,
    cPip=500,
    thickness=0.0032,
    initDelay=true,
    m_flow_start=m_flow_nominal,
    rhoPip=8000,
    T_start_in=323.15,
    T_start_out=323.15) "Pipe"
  Sensors.TemperatureTwoPort senTemOutNoMix(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    tau=0,
    T_start=323.15) "Temperature sensor"
  Sources.MassFlowSource_T souNoMix(
    redeclare package Medium = Medium,
    use_T_in=true,
    m_flow=m_flow_nominal,
    nPorts=1) "Flow source"
equation
  connect(Tin.y, sou.T_in)
  connect(pip.port_b, senTemOut.port_a)
  connect(senTemOut.port_b, sin.ports[1])
  connect(senTemIn.port_b, pip.port_a)
  connect(senTemInNoMix.port_b, pipNoMix.port_a)
  connect(pipNoMix.port_b, senTemOutNoMix.port_a)
  connect(senTemOutNoMix.port_b, sin.ports[2])
  connect(bou[1].port, pip.heatPort)
  connect(bou[2].port, pipNoMix.heatPort)
  connect(sou.ports[1], senTemIn.port_a)
  connect(souNoMix.ports[1], senTemInNoMix.port_a)
  connect(Tin.y, souNoMix.T_in)
end PlugFlowPipe;


within AixLib.Fluid.FixedResistances.Examples;
model PlugFlowPipeDiscretized "Simple example of discretized plug flow pipe"
  extends Modelica.Icons.Example;
  replaceable package Medium = AixLib.Media.Water "Medium in the pipe"

  parameter Integer nSeg=10 "Number of pipe segments";

  Modelica.Blocks.Sources.Ramp Tin(
    height=20,
    duration=0,
    offset=273.15 + 50,
    startTime=100) "Ramp pressure signal"
  Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325) "Pressure boundary condition"
  AixLib.Fluid.FixedResistances.PlugFlowPipeDiscretized pip(
    redeclare package Medium = Medium,
    nSeg=nSeg,
    dh=0.1,
    totLen=100,
    dIns=0.05,
    kIns=0.028,
    m_flow_nominal=10,
    thickness=0.0032,
    initDelay=true,
    T_start_in=fill(323.15, nSeg)) "Pipe segments"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature
    bou[nSeg](T={283.15 + 2 * i for i in 1:nSeg})
    "Boundary temperature"
  AixLib.Fluid.Sources.MassFlowSource_T sou(
    nPorts=1,
    redeclare package Medium = Medium,
    use_T_in=true,
    m_flow=10)
              "Flow source"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTemOut(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTemIn(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    T_start=323.15) "Temperature sensor"
equation
  connect(Tin.y, sou.T_in)
  connect(senTemOut.port_b, sin.ports[1])
  connect(sou.ports[1], senTemIn.port_a)
  connect(senTemIn.port_b, pip.port_a)
  connect(bou.port, pip.heatPorts)
  connect(pip.port_b, senTemOut.port_a)
end PlugFlowPipeDiscretized;


within AixLib.Fluid.FixedResistances.Examples;
model PressureDrop
  "Example model for flow resistance with nominal pressure drop as parameter"
  extends Modelica.Icons.Example;

 package Medium = AixLib.Media.Air "Medium model";

  Modelica.Blocks.Sources.Ramp P(
    duration=1,
    height=20,
    offset=101325 - 10) "Ramp pressure signal"

  AixLib.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    T=273.15 + 20,
    use_p_in=true,
    nPorts=1)
    "Pressure boundary condition"

  AixLib.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325)
    "Pressure boundary condition"

  AixLib.Fluid.FixedResistances.PressureDrop res(
    redeclare package Medium = Medium,
    m_flow_nominal=0.2,
    from_dp=true,
    dp_nominal=10)
    "Fixed resistance"

equation
  connect(P.y, sou.p_in)
  connect(sou.ports[1], res.port_a)
  connect(res.port_b, sin.ports[1])
end PressureDrop;


Medium in the system

within AixLib.Fluid.FixedResistances.Examples;
model SimplePipe

  extends Modelica.Icons.Example;

   replaceable package Medium =
      Modelica.Media.Water.ConstantPropertyLiquidWater "Medium in the system"

  Modelica.Fluid.Sources.MassFlowSource_T Source(
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    use_T_in=true,
    m_flow=0.3,
    T=323.15,
    nPorts=1)
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature fixedTemp[simplePipe.nNodes](each T=
        278.15)
  Modelica.Fluid.Sources.FixedBoundary
                                  Sink(
    redeclare package Medium = Medium, nPorts=1)
  inner Modelica.Fluid.System system
  AixLib.Fluid.FixedResistances.SimplePipe simplePipe(
    redeclare package Medium = Medium,
    nNodes=4,
    dh=0.028,
    length=10,
    lambda=0.035,
    thickness=0.001,
    T_start=323.15,
    m_flow_nominal=0.5,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
  Sensors.TemperatureTwoPort              senTemIn(
    redeclare package Medium = Medium,
    m_flow_nominal=0.001,
    T_start=323.15) "Temperature sensor"
  Sensors.TemperatureTwoPort              senTemOut(
    redeclare package Medium = Medium,
    m_flow_nominal=0.001,
    T_start=323.15) "Temperature sensor"
  Modelica.Blocks.Sources.Ramp Tin(
    height=20,
    duration=0,
    offset=273.15 + 50,
    startTime=100) "Ramp pressure signal"
equation
  connect(Source.ports[1], senTemIn.port_a)
  connect(senTemIn.port_b, simplePipe.port_a)
  connect(simplePipe.port_b, senTemOut.port_a)
  connect(senTemOut.port_b, Sink.ports[1])
  connect(Tin.y, Source.T_in)
  connect(simplePipe.heatPorts, fixedTemp.port)
end SimplePipe;


within AixLib.Fluid.FixedResistances.Validation;
model FlowJunctionSteadyState
  "Test model for the three way splitter/mixer model configured as steady-state"
  extends Modelica.Icons.Example;

 package Medium = AixLib.Media.Air "Medium model";

  AixLib.Fluid.FixedResistances.Junction spl(
    redeclare package Medium = Medium,
    m_flow_nominal={2,2,2},
    dp_nominal={5,10,15},
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState) "Splitter"

  AixLib.Fluid.Sources.Boundary_pT bou1(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    use_p_in=true,
    nPorts=1)
    "Pressure boundary condition"

  AixLib.Fluid.Sources.Boundary_pT bou2(
    redeclare package Medium = Medium,
    T=273.15 + 20,
    p(displayUnit="Pa") = 101325,
    nPorts=1)
    "Pressure boundary condition"

  AixLib.Fluid.Sources.Boundary_pT bou3(
    redeclare package Medium = Medium,
    T=273.15 + 30,
    use_p_in=true,
    nPorts=1)
    "Pressure boundary condition"

  Modelica.Blocks.Sources.Ramp P1(
    offset=101320,
    height=10,
    duration=20,
    startTime=20) "Ramp pressure signal"

  Modelica.Blocks.Sources.Ramp P3(
    offset=101320,
    height=10,
    duration=20,
    startTime=70) "Ramp pressure signal"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTem1(
    redeclare package Medium = Medium,
    m_flow_nominal=1)
    "Temperature sensor"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTem2(
    redeclare package Medium = Medium,
    m_flow_nominal=2)
    "Temperature sensor"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTem3(
    redeclare package Medium = Medium,
    m_flow_nominal=3)
    "Temperature sensor"
equation
  connect(P1.y, bou1.p_in)
  connect(bou3.p_in, P3.y)
  connect(bou3.ports[1], senTem3.port_a)
  connect(senTem3.port_b, spl.port_3)
  connect(bou1.ports[1], senTem1.port_a)
  connect(senTem1.port_b, spl.port_1)
  connect(spl.port_2, senTem2.port_a)
  connect(senTem2.port_b, bou2.ports[1])
end FlowJunctionSteadyState;


within AixLib.Fluid.FixedResistances.Validation;
model FlowJunctionSteadyStateNoPressureDrop
  "Test model for the three way splitter/mixer model configured as steady-state"
  extends Modelica.Icons.Example;

 package Medium = AixLib.Media.Air "Medium model";

  AixLib.Fluid.FixedResistances.Junction spl(
    redeclare package Medium = Medium,
    m_flow_nominal={2,2,2},
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    dp_nominal={0,0,0}) "Splitter"

  AixLib.Fluid.Sources.MassFlowSource_T bou1(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    use_m_flow_in=true) "Mass flow boundary condition"

  AixLib.Fluid.Sources.Boundary_pT bou2(
    redeclare package Medium = Medium,
    T=273.15 + 20,
    p(displayUnit="Pa") = 101325,
    nPorts=1)
    "Pressure boundary condition"

  AixLib.Fluid.Sources.MassFlowSource_T bou3(
    redeclare package Medium = Medium,
    T=273.15 + 30,
    nPorts=1,
    use_m_flow_in=true) "Mass flow boundary condition"

  Modelica.Blocks.Sources.Ramp m1_flow(
    duration=20,
    startTime=20,
    height=1,
    offset=-1) "Ramp mass flow signal"

  Modelica.Blocks.Sources.Ramp m3_flow(
    height=1,
    duration=20,
    startTime=70,
    offset=1)     "Ramp mass flow signal"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTem1(
    redeclare package Medium = Medium,
    m_flow_nominal=1)
    "Temperature sensor"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTem2(
    redeclare package Medium = Medium,
    m_flow_nominal=2)
    "Temperature sensor"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTem3(
    redeclare package Medium = Medium,
    m_flow_nominal=3)
    "Temperature sensor"
equation
  connect(bou3.ports[1], senTem3.port_a)
  connect(senTem3.port_b, spl.port_3)
  connect(bou1.ports[1], senTem1.port_a)
  connect(senTem1.port_b, spl.port_1)
  connect(spl.port_2, senTem2.port_a)
  connect(senTem2.port_b, bou2.ports[1])
  connect(m1_flow.y, bou1.m_flow_in)
  connect(m3_flow.y, bou3.m_flow_in)
end FlowJunctionSteadyStateNoPressureDrop;


Validation model for lossless pipe

within AixLib.Fluid.FixedResistances.Validation;
model LosslessPipe "Validation model for lossless pipe"
  extends Modelica.Icons.Example;

 package Medium = AixLib.Media.Air "Medium model";

  Modelica.Blocks.Sources.Ramp m_flow(
    duration=1,
    offset=-1,
    height=2)  "Mass flow source"

  AixLib.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    nPorts=1,
    use_m_flow_in=true,
    T=273.15 + 20)
    "Pressure boundary condition"

  AixLib.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325)
    "Pressure boundary condition"

  AixLib.Fluid.FixedResistances.LosslessPipe res(
    redeclare package Medium = Medium,
    show_T=true,
    m_flow_nominal=1)
    "Fixed resistance"

equation
  connect(sou.ports[1], res.port_a)
  connect(res.port_b, sin.ports[1])
  connect(m_flow.y, sou.m_flow_in)
end LosslessPipe;


Collection of validation models

within AixLib.Fluid.FixedResistances;
package Validation "Collection of validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Test of multiple resistances in series

within AixLib.Fluid.FixedResistances.Validation;
model PressureDropsExplicit "Test of multiple resistances in series"
  extends Modelica.Icons.Example;

 package Medium = AixLib.Media.Air "Medium model";
  AixLib.Fluid.Sources.Boundary_ph sou(
   redeclare package Medium = Medium,
    nPorts=1,
    p(displayUnit="Pa") = 101335,
    use_p_in=true) "Pressure boundary condition"

  AixLib.Fluid.Sources.Boundary_ph sin(
    redeclare package Medium = Medium,
    nPorts=1,
    use_p_in=false,
    p=101325)
    "Pressure boundary condition"

  AixLib.Fluid.FixedResistances.PressureDrop res11(
    redeclare package Medium = Medium,
    from_dp=false,
    m_flow_nominal=2,
    dp_nominal=5) "Flow resistance"

  AixLib.Fluid.FixedResistances.PressureDrop res12(
    redeclare package Medium = Medium,
    from_dp=false,
    m_flow_nominal=2,
    dp_nominal=5) "Flow resistance"

  AixLib.Fluid.FixedResistances.PressureDrop res22(
    redeclare package Medium = Medium,
    m_flow_nominal=2,
    dp_nominal=5,
    from_dp=true) "Flow resistance"

  AixLib.Fluid.FixedResistances.PressureDrop res21(
    redeclare package Medium = Medium,
    m_flow_nominal=2,
    dp_nominal=5,
    from_dp=true) "Flow resistance"

  AixLib.Fluid.FixedResistances.PressureDrop res31(
    redeclare package Medium = Medium,
    from_dp=false,
    m_flow_nominal=2,
    dp_nominal=5) "Flow resistance"

  AixLib.Fluid.FixedResistances.PressureDrop res32(
    redeclare package Medium = Medium,
    from_dp=false,
    m_flow_nominal=2,
    dp_nominal=5) "Flow resistance"

  AixLib.Fluid.FixedResistances.PressureDrop res42(
    redeclare package Medium = Medium,
    m_flow_nominal=2,
    dp_nominal=5,
    from_dp=true) "Flow resistance"

  AixLib.Fluid.FixedResistances.PressureDrop res41(
    redeclare package Medium = Medium,
    m_flow_nominal=2,
    dp_nominal=5,
    from_dp=true) "Flow resistance"

  AixLib.Fluid.Sources.MassFlowSource_h bou(
    redeclare package Medium = Medium,
    m_flow=1,
    nPorts=1) "Mass flow boundary condition"

  AixLib.Fluid.Sources.MassFlowSource_h bou1(
    redeclare package Medium = Medium,
    m_flow=1,
    nPorts=1) "Mass flow boundary condition"

  AixLib.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=2,
    use_p_in=false,
    p=101325) "Pressure boundary condition"

  AixLib.Fluid.Sources.Boundary_ph sin2(
    redeclare package Medium = Medium,
    nPorts=1,
    use_p_in=false,
    p=101325) "Pressure boundary condition"

  AixLib.Fluid.Sources.Boundary_ph sou1(
    redeclare package Medium = Medium,
    nPorts=1,
    p(displayUnit="Pa") = 101335,
    use_p_in=true) "Pressure boundary condition"

  Modelica.Blocks.Sources.Ramp P(
    duration=1,
    height=20,
    offset=101315) "Signal source"

  AixLib.Fluid.Sensors.MassFlowRate senMasFlo1(
    redeclare package Medium = Medium) "Mass flow rate sensor"

  AixLib.Fluid.Sensors.MassFlowRate senMasFlo2(
    redeclare package Medium = Medium) "Mass flow rate sensor"

  AixLib.Fluid.Sensors.MassFlowRate senMasFlo3(
    redeclare package Medium = Medium) "Mass flow rate sensor"

  AixLib.Fluid.Sensors.MassFlowRate senMasFlo4(
    redeclare package Medium = Medium) "Mass flow rate sensor"

  AixLib.Utilities.Diagnostics.AssertEquality assertEquality(threShold=1E-1)
    "Assert equality of the two mass flow rates"

  AixLib.Utilities.Diagnostics.AssertEquality assertEquality1(threShold=1E-1)
    "Assert equality of the two mass flow rates"
equation
  connect(res11.port_b, res12.port_a)
  connect(res21.port_b, res22.port_a)
  connect(res31.port_b, res32.port_a)
  connect(res41.port_b, res42.port_a)
  connect(sou.ports[1], res11.port_a)
  connect(bou.ports[1], res31.port_a)
  connect(bou1.ports[1], res41.port_a)
  connect(sou1.ports[1], res21.port_a)
  connect(P.y, sou.p_in)
  connect(P.y, sou1.p_in)
  connect(res12.port_b, senMasFlo1.port_a)
  connect(res22.port_b, senMasFlo2.port_a)
  connect(res32.port_b, senMasFlo3.port_a)
  connect(res42.port_b, senMasFlo4.port_a)
  connect(senMasFlo3.port_b, sin1.ports[1])
  connect(senMasFlo4.port_b, sin1.ports[2])
  connect(senMasFlo1.port_b, sin.ports[1])
  connect(senMasFlo2.port_b, sin2.ports[1])
  connect(senMasFlo3.m_flow, assertEquality1.u1)
  connect(senMasFlo4.m_flow, assertEquality1.u2)
  connect(senMasFlo1.m_flow, assertEquality.u1)
  connect(senMasFlo2.m_flow, assertEquality.u2)
end PressureDropsExplicit;


Test of multiple linearized resistances in series. This model tests multiple linearized flow resistances in series.

within AixLib.Fluid.FixedResistances.Validation;
model PressureDropsExplicitLinearized
  "Test of multiple linearized resistances in series"
  extends PressureDropsExplicit(
    res11(linearized=true),
    res12(linearized=true),
    res21(linearized=true),
    res22(linearized=true),
    res31(linearized=true),
    res32(linearized=true),
    res41(linearized=true),
    res42(linearized=true));
end PressureDropsExplicitLinearized;


within AixLib.Fluid.FixedResistances.Validation;
model PressureDropsParallel
   "Test with multiple resistances in parallel"
  extends Modelica.Icons.Example;

 package Medium = AixLib.Media.Water "Medium model";

    Modelica.Blocks.Sources.Ramp P(
      duration=1,
      height=20,
      offset=101315) "Signal source"

  AixLib.Fluid.FixedResistances.PressureDrop res1(
    redeclare package Medium = Medium,
    m_flow_nominal=5,
    dp_nominal=10,
    deltaM=0.3,
    linearized=false,
    from_dp=true) "Flow resistance"

  AixLib.Fluid.Sources.Boundary_pT sou1(
    redeclare package Medium = Medium,
    nPorts=2,
    use_p_in=true,
    T=293.15) "Pressure boundary condition"

  AixLib.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = Medium,
    nPorts=2,
    p(displayUnit="Pa") = 101325,
    T=283.15) "Pressure boundary condition"

  AixLib.Fluid.FixedResistances.PressureDrop res2(
    redeclare package Medium = Medium,
    m_flow_nominal=5,
    dp_nominal=10,
    deltaM=0.3,
    linearized=false,
    from_dp=true) "Flow resistance"

  AixLib.Fluid.Sensors.MassFlowRate masFlo2(redeclare package Medium = Medium)
    "Mass flow rate sensor"
  AixLib.Utilities.Diagnostics.AssertEquality assEqu(
    message="Inputs differ, check that lossless pipe is correctly implemented.",
      threShold=1E-4)
    "Assert equality of the two mass flow rates"

  AixLib.Fluid.Sensors.MassFlowRate masFlo1(redeclare package Medium = Medium)
    "Mass flow rate sensor"

equation
  connect(P.y, sou1.p_in)
  connect(res2.port_b, masFlo2.port_a)
  connect(res1.port_b, masFlo1.port_a)
  connect(sou1.ports[1], res1.port_a)
  connect(sou1.ports[2], res2.port_a)
  connect(sin1.ports[1], masFlo1.port_b)
  connect(sin1.ports[2], masFlo2.port_b)
  connect(masFlo2.m_flow, assEqu.u1)
  connect(masFlo1.m_flow, assEqu.u2)
end PressureDropsParallel;


Test of multiple resistances in series

within AixLib.Fluid.FixedResistances.Validation;
model PressureDropsSeries "Test of multiple resistances in series"
  extends Modelica.Icons.Example;

 package Medium = AixLib.Media.Air "Medium model";

   parameter Integer nRes(min=2) = 10 "Number of resistances";

  parameter Modelica.Units.SI.PressureDifference dp_nominal=5
    "Nominal pressure drop for each resistance";

   Modelica.Blocks.Sources.Ramp P(
    duration=1,
    height=2*dp_nominal*nRes,
    offset=101325 - dp_nominal*nRes) "Signal source"
  AixLib.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    T=273.15 + 20,
    use_p_in=true,
    nPorts=1) "Pressure boundary condition"

  AixLib.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325) "Pressure boundary condition"

  AixLib.Fluid.FixedResistances.PressureDrop[nRes] res(
    redeclare each package Medium = Medium,
    each dp_nominal=dp_nominal,
    each from_dp=false,
    each m_flow_nominal=2) "Flow resistance"

equation
  for i in 1:nRes-1 loop
    connect(res[i].port_b, res[i+1].port_a)
  end for;
  connect(P.y, sou.p_in)
  connect(sin.ports[1], res[nRes].port_b)
  connect(sou.ports[1], res[1].port_a)
end PressureDropsSeries;


within AixLib.Fluid.FixedResistances.Validation.PlugFlowPipes;
model FlowReversal
  "Simple example of plug flow pipe with flow reversal"
  extends Modelica.Icons.Example;
  package Medium = AixLib.Media.Water "Medium in the pipe";
  Modelica.Blocks.Sources.Step m_flow(
    height=-4,
    offset=2,
    startTime=50)  "Mass flow rate signal"
  Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    nPorts=1,
    p(displayUnit="bar") = 500000,
    T=313.15) "Pressure boundary condition"
  AixLib.Fluid.FixedResistances.PlugFlowPipe pip(
    redeclare package Medium = Medium,
    dIns=0.05,
    kIns=0.028,
    cPip=500,
    thickness=0.0032,
    rhoPip=8000,
    m_flow_nominal=2,
    initDelay=true,
    length=200,
    v_nominal=2,
    T_start_in=293.15,
    T_start_out=293.15) "Pipe"
  AixLib.Fluid.Sources.MassFlowSource_T sou(
    nPorts=1,
    redeclare package Medium = Medium,
    m_flow=0,
    use_m_flow_in=true,
    T=303.15) "Flow source"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTemOut(
    redeclare package Medium = Medium,
    tau=0,
    T_start=323.15,
    m_flow_nominal=2)
    "Temperature sensor"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTemIn(
    redeclare package Medium = Medium,
    tau=0,
    T_start=323.15,
    m_flow_nominal=2)
    "Temperature sensor"
equation
  connect(pip.port_b, senTemOut.port_a)
  connect(senTemOut.port_b, sin.ports[1])
  connect(sou.ports[1], senTemIn.port_a)
  connect(senTemIn.port_b, pip.port_a)
  connect(m_flow.y, sou.m_flow_in)
end FlowReversal;


within AixLib.Fluid.FixedResistances.Validation.PlugFlowPipes;
model MSLAIT
  "Validation pipe against data from Austrian Institute of Technology with standard library components"
  extends Modelica.Icons.Example;

  Fluid.Sources.MassFlowSource_T Point1(
    redeclare package Medium = Medium,
    use_T_in=true,
    use_m_flow_in=true,
    nPorts=1) "Mass flow source"
  package Medium = AixLib.Media.Water;
  Fluid.Sources.MassFlowSource_T Point4(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Substation 4"
  Fluid.Sources.MassFlowSource_T Point3(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Substation 3"
  Fluid.Sources.MassFlowSource_T Point2(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Substation 2"
  Modelica.Blocks.Sources.CombiTimeTable DataReader(
    tableOnFile=true,
    tableName="dat",
    columns=2:pipeDataAIT151218.nCol,
    fileName=pipeDataAIT151218.filNam)
    "Read measurement data"
  Data.PipeDataAIT151218 pipeDataAIT151218 "Record with measurement data"
  Modelica.Blocks.Sources.RealExpression m_flow_p3(y=-DataReader.y[7])
    "Mass flow rate for substation 3"
  Modelica.Blocks.Sources.RealExpression m_flow_p2(y=-DataReader.y[6])
    "Mass flow rate for substation 2"
  Modelica.Blocks.Sources.RealExpression T_p1(y=DataReader.y[1])
    "Inlet temperature"
  AixLib.Fluid.Sources.Boundary_pT ExcludedBranch(redeclare package Medium = Medium,
      nPorts=1) "Mass flow sink for excluded branch"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature
    prescribedTemperature "Variable environment temperature"

  parameter Boolean allowFlowReversal=false
    "= true to allow flow reversal, false restricts to design direction (port_a -> port_b)";
  Modelica.Fluid.Pipes.DynamicPipe pip0(
    nParallel=1,
    diameter=0.0825,
    redeclare package Medium = Medium,
    use_HeatTransfer=true,
    length=20,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    nNodes=20,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
          dp_nominal(displayUnit="Pa") = 10*pip0.length, m_flow_nominal=0.3),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Pipe 0"
  inner Modelica.Fluid.System system
  parameter Modelica.Units.SI.ThermalResistance R=1/(2*kIns*Modelica.Constants.pi)
      *log(0.18/0.0899) + 1/(2*2.4*Modelica.Constants.pi)*log(2/0.18)
    "Thermal resistance of main pipes";
  parameter Modelica.Units.SI.ThermalResistance R80=1/(2*0.024*Modelica.Constants.pi)
      *log(0.07/0.0337) + 1/(2*2.4*Modelica.Constants.pi)*log(2/0.07)
    "Thermal resistance of service pipes";

  Modelica.Thermal.HeatTransfer.Components.ThermalResistor res0[pip0.nNodes](each R=
        R) "Thermal resistances for pipe 0"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector col0(m=pip0.nNodes)
    "Combine heat flows to one"
  Modelica.Fluid.Pipes.DynamicPipe pip1(
    nParallel=1,
    diameter=0.0825,
    redeclare package Medium = Medium,
    use_HeatTransfer=true,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    length=115,
    nNodes=115,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
          m_flow_nominal=0.3, dp_nominal=10*pip1.length),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Pipe 1"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector col1(m=pip1.nNodes)
    "Combine heat flows to one"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor res1[pip1.nNodes](each R=
        R) "Thermal resistances for pipe 1"
  Modelica.Fluid.Pipes.DynamicPipe pip2(
    nParallel=1,
    redeclare package Medium = Medium,
    use_HeatTransfer=true,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    length=76,
    nNodes=76,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
          dp_nominal=10*pip2.length, m_flow_nominal=0.3),
    diameter=0.0337 - 2*0.0032,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Pipe 2"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector col2(m=pip2.nNodes)
    "Combine heat flows to one"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor res2[pip2.nNodes](each R=
        R80) "Thermal resistances for pipe 2"
  Modelica.Fluid.Pipes.DynamicPipe pip3(
    nParallel=1,
    redeclare package Medium = Medium,
    use_HeatTransfer=true,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    length=38,
    nNodes=38,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
          dp_nominal=10*pip3.length, m_flow_nominal=0.3),
    diameter=0.0337 - 2*0.0032,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Pipe 3"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector col3(m=pip3.nNodes)
    "Combine heat flows to one"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor res3[pip3.nNodes](each R=
        R80) "Thermal resistances for pipe 3"
  Modelica.Fluid.Pipes.DynamicPipe pip4(
    nParallel=1,
    redeclare package Medium = Medium,
    use_HeatTransfer=true,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    length=29,
    nNodes=29,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
          dp_nominal=10*pip4.length, m_flow_nominal=0.3),
    diameter=0.0337 - 2*0.0032,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Pipe 4"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector col4(m=pip4.nNodes)
    "Combine heat flows to one"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor res4[pip4.nNodes](each R=
        R80) "Thermal resistances for pipe 4"
  Modelica.Fluid.Pipes.DynamicPipe pip5(
    nParallel=1,
    diameter=0.0825,
    redeclare package Medium = Medium,
    use_HeatTransfer=true,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    length=20,
    nNodes=20,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
          dp_nominal=10*pip5.length, m_flow_nominal=0.3),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Pipe 5"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector col5(m=pip5.nNodes)
    "Combine heat flows to one"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor res5[pip5.nNodes](each R=
        R) "Thermal resistances for pipe 5"
  parameter Modelica.Units.SI.ThermalConductivity kIns=0.024
    "Heat conductivity of pipe insulation material";
  parameter Modelica.Units.SI.Length dIns=0.045 "Thickness of pipe insulation";
  parameter Modelica.Units.SI.Diameter diameter=0.089 "Outer diameter of pipe";
  Fluid.Sensors.TemperatureTwoPort
                            senTem_p2(redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"
  Fluid.Sensors.TemperatureTwoPort
                            senTem_p3(redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"
  Fluid.Sensors.TemperatureTwoPort senTemIn_p2(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"
  Fluid.Sensors.TemperatureTwoPort
                            senTem_p1(redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"
  Fluid.Sensors.TemperatureTwoPort
                            senTem_p4(redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=1
    "Nominal mass flow rate, used for regularization near zero flow";
  parameter Modelica.Units.SI.Time tauHeaTra=6500
    "Time constant for heat transfer, default 20 minutes";

  Fluid.Sources.MassFlowSource_T Point5(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Mass flow sink for substation 4 in case of low flow rates"
  Modelica.Blocks.Sources.RealExpression m_flow_p4(y=-DataReader.y[8])
    "Measured mass flow rate for substation 4"
  Modelica.Blocks.Logical.Switch switch
    "Switch to avoid mass flow rate measurement noise on substation with flow standstill."
  Modelica.Blocks.Sources.RealExpression m_flow_zero(y=0)
    "Default value when mass flow rate is below noise threshold"
  Modelica.Blocks.Logical.LessThreshold lessThreshold(threshold=-0.001)
    "Check if mass flow rate is lower than 0.001"
  Modelica.Blocks.Logical.Switch switch1
    "If flow is lower than measurement noise threshold, bypass temperature sensor"
equation
  connect(m_flow_p3.y, Point3.m_flow_in)
  connect(Point2.m_flow_in, m_flow_p2.y)
  connect(T_p1.y, Point1.T_in)
  connect(DataReader.y[5], Point1.m_flow_in)
  connect(DataReader.y[9], prescribedTemperature.T)
  connect(pip0.port_b, ExcludedBranch.ports[1])
  connect(pip4.port_a, pip1.port_b)
  connect(pip5.port_a, pip1.port_b)
  connect(pip1.port_a, pip0.port_b)
  connect(pip2.port_b, senTem_p2.port_a)
  connect(senTem_p2.port_b, Point2.ports[1])
  connect(senTem_p3.port_a, pip3.port_b)
  connect(senTem_p3.port_b, Point3.ports[1])
  connect(pip3.port_a, pip5.port_b)
  connect(senTemIn_p2.port_a, pip5.port_b)
  connect(senTemIn_p2.port_b, pip2.port_a)
  connect(pip4.port_b, senTem_p4.port_a)
  connect(senTem_p4.port_b, Point4.ports[1])
  connect(senTem_p1.port_a, Point1.ports[1])
  connect(senTem_p1.port_b, pip0.port_a)
  connect(Point5.ports[1], senTem_p4.port_a)
  connect(pip2.heatPorts, res2.port_a)
  connect(res2.port_b, col2.port_a)
  connect(pip5.heatPorts, res5.port_a)
  connect(res5.port_b, col5.port_a)
  connect(res4.port_a, pip4.heatPorts)
  connect(res4.port_b, col4.port_a)
  connect(pip3.heatPorts, res3.port_a)
  connect(res3.port_b, col3.port_a)
  connect(res1.port_a, pip1.heatPorts)
  connect(res1.port_b, col1.port_a)
  connect(pip0.heatPorts, res0.port_a)
  connect(res0.port_b, col0.port_a)
  connect(col2.port_b, col5.port_b)
  connect(col5.port_b, col4.port_b)
  connect(col0.port_b, prescribedTemperature.port)
  connect(col3.port_b, prescribedTemperature.port)
  connect(col4.port_b, prescribedTemperature.port)
  connect(m_flow_zero.y,switch. u3)
  connect(switch.u1,m_flow_p4. y)
  connect(Point4.m_flow_in,switch. y)
  connect(switch.u2,lessThreshold. y)
  connect(lessThreshold.u,m_flow_p4. y)
  connect(lessThreshold.y,switch1. u2)
  connect(m_flow_p4.y,switch1. u3)
  connect(m_flow_zero.y,switch1. u1)
  connect(switch1.y, Point5.m_flow_in)
  connect(col1.port_b, prescribedTemperature.port)
end MSLAIT;


within AixLib.Fluid.FixedResistances.Validation.PlugFlowPipes;
model MSLAIT2Nodes
  "Smaller discretisation. Validation pipe against data from Austrian Institute of Technology with standard library components"
  extends Modelica.Icons.Example;

  Fluid.Sources.MassFlowSource_T Point1(
    redeclare package Medium = Medium,
    use_T_in=true,
    use_m_flow_in=true,
    nPorts=1)
  package Medium = AixLib.Media.Water;
  Fluid.Sources.MassFlowSource_T Point4(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Substation 4"
  Fluid.Sources.MassFlowSource_T Point3(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Substation 3"
  Fluid.Sources.MassFlowSource_T Point2(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Substation 2"
  Modelica.Blocks.Sources.CombiTimeTable DataReader(
    tableOnFile=true,
    tableName="dat",
    columns=2:pipeDataAIT151218.nCol,
    fileName=pipeDataAIT151218.filNam)
    "Read measurement data"
  Data.PipeDataAIT151218 pipeDataAIT151218 "Measurement data from AIT"
  Modelica.Blocks.Sources.RealExpression m_flow_p3(y=-DataReader.y[7])
    "Mass flow rate for substation 3"
  Modelica.Blocks.Sources.RealExpression m_flow_p4(y=-DataReader.y[8])
    "Mass flow rate for substation 4"
  Modelica.Blocks.Sources.RealExpression m_flow_p2(y=-DataReader.y[6])
    "Mass flow rate for substation 2"
  Modelica.Blocks.Sources.RealExpression T_p1(y=DataReader.y[1])
    "Inlet temperature"
  AixLib.Fluid.Sources.Boundary_pT ExcludedBranch(redeclare package Medium = Medium,
      nPorts=1) "Mass flow sink for excluded branch"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature
    prescribedTemperature "Variable environment temperature"

  parameter Boolean allowFlowReversal=false
    "= true to allow flow reversal, false restricts to design direction (port_a -> port_b)";
  Modelica.Fluid.Pipes.DynamicPipe pip0(
    nParallel=1,
    diameter=0.0825,
    redeclare package Medium = Medium,
    use_HeatTransfer=true,
    length=20,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
          dp_nominal(displayUnit="Pa") = 10*pip0.length, m_flow_nominal=0.3),
    nNodes=2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Pipe 0"
  inner Modelica.Fluid.System system
  parameter Real R(unit="(m.K)/W")=1/(2*kIns*Modelica.Constants.pi)
      *log(0.18/0.0899) + 1/(2*2.4*Modelica.Constants.pi)*log(2/0.18) "Thermal resistance per unit length of main pipes";
  parameter Real R80(unit="(m.K)/W")=1/(2*0.024*Modelica.Constants.pi)
      *log(0.07/0.0337) + 1/(2*2.4*Modelica.Constants.pi)*log(2/0.07) "Thermal resistance per unit length of service pipes";

  Modelica.Thermal.HeatTransfer.Components.ThermalResistor res0[pip0.nNodes](each R=
        2*R/pip0.length) "Thermal resistances for elements of pipe 0"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector col0(m=pip0.nNodes)
    "Combine heat flows to one"
  Modelica.Fluid.Pipes.DynamicPipe pip1(
    nParallel=1,
    diameter=0.0825,
    redeclare package Medium = Medium,
    use_HeatTransfer=true,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    length=115,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
          m_flow_nominal=0.3, dp_nominal=10*pip1.length),
    nNodes=2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Pipe 1"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector col1(m=pip1.nNodes)
    "Combine heat flows to one"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor res1[pip1.nNodes](each R=
        2*R/pip1.length) "Thermal resistances for elements of pipe 1"
  Modelica.Fluid.Pipes.DynamicPipe pip2(
    nParallel=1,
    redeclare package Medium = Medium,
    use_HeatTransfer=true,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    length=76,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
          dp_nominal=10*pip2.length, m_flow_nominal=0.3),
    diameter=0.0337 - 2*0.0032,
    nNodes=2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Pipe 2"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector col2(m=pip2.nNodes)
    "Combine heat flows to one"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor res2[pip2.nNodes](each R=
        2*R80/pip2.length) "Thermal resistances for elements of pipe 2"
  Modelica.Fluid.Pipes.DynamicPipe pip3(
    nParallel=1,
    redeclare package Medium = Medium,
    use_HeatTransfer=true,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    length=38,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
          dp_nominal=10*pip3.length, m_flow_nominal=0.3),
    diameter=0.0337 - 2*0.0032,
    nNodes=2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Pipe 3"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector col3(m=pip3.nNodes)
    "Combine heat flows to one"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor res3[pip3.nNodes](each R=
        2*R80/pip3.length) "Thermal resistances for elements of pipe 3"
  Modelica.Fluid.Pipes.DynamicPipe pip4(
    nParallel=1,
    redeclare package Medium = Medium,
    use_HeatTransfer=true,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    length=29,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
          dp_nominal=10*pip4.length, m_flow_nominal=0.3),
    diameter=0.0337 - 2*0.0032,
    nNodes=2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Pipe 4"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector col4(m=pip4.nNodes)
    "Combine heat flows to one"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor res4[pip4.nNodes](each R=
        2*R80/pip4.length) "Thermal resistances for elements of pipe 4"
  Modelica.Fluid.Pipes.DynamicPipe pip5(
    nParallel=1,
    diameter=0.0825,
    redeclare package Medium = Medium,
    use_HeatTransfer=true,
    redeclare model HeatTransfer =
        Modelica.Fluid.Pipes.BaseClasses.HeatTransfer.IdealFlowHeatTransfer,
    length=20,
    redeclare model FlowModel =
        Modelica.Fluid.Pipes.BaseClasses.FlowModels.NominalTurbulentPipeFlow (
          dp_nominal=10*pip5.length, m_flow_nominal=0.3),
    nNodes=2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Pipe 5"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector col5(m=pip5.nNodes)
    "Combine heat flows to one"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor res5[pip5.nNodes](each R=
        2*R/pip5.length) "Thermal resistances for elements of pipe 5"
  parameter Modelica.Units.SI.ThermalConductivity kIns=0.024
    "Heat conductivity";
  parameter Modelica.Units.SI.Length dIns=0.045 "Thickness of pipe insulation";
  parameter Modelica.Units.SI.Diameter diameter=0.089 "Outer diameter of pipe";
  Fluid.Sensors.TemperatureTwoPort
                            senTem_p2(redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"
  Fluid.Sensors.TemperatureTwoPort
                            senTem_p3(redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"
  Fluid.Sensors.TemperatureTwoPort senTemIn_p2(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"
  Fluid.Sensors.TemperatureTwoPort senTem_p1(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"
  Fluid.Sensors.TemperatureTwoPort senTem_p4(
  redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=1
    "Nominal mass flow rate, used for regularization near zero flow";
  parameter Modelica.Units.SI.Time tauHeaTra=6500
    "Time constant for heat transfer, default 20 minutes";

  Modelica.Blocks.Logical.Switch switch
    "Decide if mass flow rate is below measurement noise threshold or not"
  Modelica.Blocks.Sources.RealExpression m_flow_zero(y=0)
    "Default value when mass flow rate is below measurement noise threshold"
  Modelica.Blocks.Logical.LessThreshold lessThreshold(threshold=-0.001)
    "Measurement noise threshold"
  Fluid.Sources.MassFlowSource_T Point5(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Low flow bypass of substation 4"
  Modelica.Blocks.Logical.Switch switch1
    "Decide if mass flow rate is below measurement noise threshold or not"
equation
  connect(m_flow_p3.y, Point3.m_flow_in)
  connect(Point2.m_flow_in, m_flow_p2.y)
  connect(T_p1.y, Point1.T_in)
  connect(DataReader.y[5], Point1.m_flow_in)
  connect(DataReader.y[9], prescribedTemperature.T)
  connect(pip0.port_b, ExcludedBranch.ports[1])
  connect(pip4.port_a, pip1.port_b)
  connect(pip5.port_a, pip1.port_b)
  connect(pip1.port_a, pip0.port_b)
  connect(pip2.port_b, senTem_p2.port_a)
  connect(senTem_p2.port_b, Point2.ports[1])
  connect(senTem_p3.port_a, pip3.port_b)
  connect(senTem_p3.port_b, Point3.ports[1])
  connect(pip3.port_a, pip5.port_b)
  connect(senTemIn_p2.port_a, pip5.port_b)
  connect(senTemIn_p2.port_b, pip2.port_a)
  connect(pip4.port_b, senTem_p4.port_a)
  connect(senTem_p4.port_b, Point4.ports[1])
  connect(senTem_p1.port_a, Point1.ports[1])
  connect(senTem_p1.port_b, pip0.port_a)
  connect(m_flow_zero.y,switch. u3)
  connect(switch.u1, m_flow_p4.y)
  connect(Point4.m_flow_in, switch.y)
  connect(switch.u2, lessThreshold.y)
  connect(lessThreshold.u, m_flow_p4.y)
  connect(Point5.m_flow_in,switch1. y)
  connect(lessThreshold.y, switch1.u2)
  connect(m_flow_p4.y, switch1.u3)
  connect(m_flow_zero.y, switch1.u1)
  connect(Point5.ports[1], senTem_p4.port_a)
  connect(pip2.heatPorts, res2.port_a)
  connect(res2.port_b, col2.port_a)
  connect(col5.port_a, res5.port_b)
  connect(res5.port_a, pip5.heatPorts)
  connect(res4.port_a, pip4.heatPorts)
  connect(res4.port_b, col4.port_a)
  connect(col2.port_b, col5.port_b)
  connect(col5.port_b, col4.port_b)
  connect(pip1.heatPorts, res1.port_a)
  connect(res1.port_b, col1.port_a)
  connect(col4.port_b, col1.port_b)
  connect(pip0.heatPorts, res0.port_a)
  connect(res0.port_b, col0.port_a)
  connect(col1.port_b, col0.port_b)
  connect(col0.port_b, prescribedTemperature.port)
  connect(pip3.heatPorts, res3.port_a)
  connect(res3.port_b, col3.port_a)
  connect(col3.port_b, prescribedTemperature.port)
end MSLAIT2Nodes;


<html>
<p>
This package contains models that validate the pipe models against measured data
from real district heating networks.

</p>
</html>

within AixLib.Fluid.FixedResistances.Validation;
package PlugFlowPipes
extends Modelica.Icons.ExamplesPackage;
end PlugFlowPipes;


within AixLib.Fluid.FixedResistances.Validation.PlugFlowPipes;
model PlugFlowAIT
  "Validation pipe against data from Austrian Institute of Technology"
  extends Modelica.Icons.Example;
  package Medium = AixLib.Media.Water;
  parameter Modelica.Units.SI.Length Lcap=1
    "Length over which transient effects typically take place";
  parameter Real R80(unit="(m.K)/W")=1/(2*0.024*Modelica.Constants.pi)
      *log(0.07/0.0337) + 1/(2*2.4*Modelica.Constants.pi)*log(2/0.07) "Thermal resistance per unit length of service pipes";

  parameter Boolean pipVol=true
    "Flag to decide whether volumes are included at the end points of the pipe";
  parameter Boolean allowFlowReversal=true
    "= true to allow flow reversal, false restricts to design direction (port_a -> port_b)";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=1
    "Nominal mass flow rate, used for regularization near zero flow";
  parameter Modelica.Units.SI.Time tauHeaTra=6500
    "Time constant for heat transfer, default 20 minutes";

  parameter Modelica.Units.SI.Length thickness=0.0032 "Pipe wall thickness";

  Fluid.Sources.MassFlowSource_T Point1(
    redeclare package Medium = Medium,
    use_T_in=true,
    use_m_flow_in=true,
    nPorts=1) "Mass flow source"

  Fluid.Sources.MassFlowSource_T Point4(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Substation 4"
  Fluid.Sources.MassFlowSource_T Point3(
    nPorts=1,
    redeclare package Medium = Medium,
    use_m_flow_in=true) "Subsation 3"
  Fluid.Sources.MassFlowSource_T Point2(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Subtation 2"
  PlugFlowPipe pip1(
    redeclare package Medium = Medium,
    dh=0.0825,
    dIns=0.045,
    kIns=0.024,
    length=115,
    allowFlowReversal=allowFlowReversal,
    m_flow_nominal=0.3,
    R=1/(2*0.024*Modelica.Constants.pi)*log(0.18/0.0899) + 1/(2*2.4*Modelica.Constants.pi)
        *log(2/0.18),
    thickness=thickness,
    cPip=500,
    rhoPip=8000,
    initDelay=false,
    m_flow_start=0) "Pipe 1"
  PlugFlowPipe pip4(
    dh = 0.0337 - 2*0.0032,
    redeclare package Medium = Medium,
    length=29,
    dIns=0.045,
    kIns=0.024,
    allowFlowReversal=allowFlowReversal,
    m_flow_nominal=0.3,
    thickness=thickness,
    R=R80,
    cPip=500,
    rhoPip=8000,
    initDelay=false,
    m_flow_start=0) "Pipe 4"

  PlugFlowPipe pip5(
    redeclare package Medium = Medium,
    length=20,
    dh=0.0825,
    kIns=0.024,
    dIns=0.045,
    allowFlowReversal=allowFlowReversal,
    m_flow_nominal=0.3,
    R=1/(2*0.024*Modelica.Constants.pi)*log(0.18/0.0899) + 1/(2*2.4*Modelica.Constants.pi)
        *log(2/0.18),
    thickness=thickness,
    cPip=500,
    rhoPip=8000,
    initDelay=false,
    m_flow_start=0) "Pipe 5"

  PlugFlowPipe pip2(
    redeclare package Medium = Medium,
    length=76,
    dIns=0.045,
    kIns=0.024,
    allowFlowReversal=allowFlowReversal,
    m_flow_nominal=0.3,
    thickness=thickness,
    dh=0.0337 - 2*0.0032,
    R=R80,
    cPip=500,
    rhoPip=8000,
    initDelay=false,
    m_flow_start=0) "Pipe 2"

  PlugFlowPipe pip3(
    redeclare package Medium = Medium,
    length=38,
    dIns=0.045,
    kIns=0.024,
    allowFlowReversal=allowFlowReversal,
    m_flow_nominal=0.3,
    thickness=thickness,
    dh=0.0337 - 2*0.0032,
    R=R80,
    cPip=500,
    rhoPip=8000,
    initDelay=false,
    m_flow_start=0) "Pipe 3"
  Modelica.Blocks.Sources.CombiTimeTable DataReader(
    tableOnFile=true,
    tableName="dat",
    columns=2:pipeDataAIT151218.nCol,
    fileName=pipeDataAIT151218.filNam)
    "Read measurement data"
  Data.PipeDataAIT151218 pipeDataAIT151218 "Measurement data from AIT network"
  Modelica.Blocks.Sources.RealExpression m_flow_p3(y=-DataReader.y[7])
    "Mass flow rate for substation 3"
  Modelica.Blocks.Sources.RealExpression m_flow_p4(y=-DataReader.y[8])
    "Mass flow rate of substation 4"
  Modelica.Blocks.Sources.RealExpression m_flow_p2(y=-DataReader.y[6])
  Modelica.Blocks.Sources.RealExpression T_p1(y=DataReader.y[1])
    "Inlet temperature"
  Fluid.Sensors.TemperatureTwoPort senTem_p3(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"
  Fluid.Sensors.TemperatureTwoPort senTem_p2(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"
  Fluid.Sensors.TemperatureTwoPort senTem_p4(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"
  Fluid.Sensors.TemperatureTwoPort senTem_p1(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"
  PlugFlowPipe pip0(
    redeclare package Medium = Medium,
    dh=0.0825,
    dIns=0.045,
    kIns=0.024,
    length=20,
    allowFlowReversal=allowFlowReversal,
    m_flow_nominal=0.3,
    R=1/(2*0.024*Modelica.Constants.pi)*log(0.18/0.0899) + 1/(2*2.4*Modelica.Constants.pi)
        *log(2/0.18),
    thickness=thickness,
    cPip=500,
    rhoPip=8000,
    initDelay=false,
    m_flow_start=0) "Pipe 0"
  AixLib.Fluid.Sources.Boundary_pT ExcludedBranch(redeclare package Medium = Medium,
      nPorts=1) "Mass flow sink for excluded branch"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature
    prescribedTemperature "Variable environment temperature"
  Fluid.Sensors.TemperatureTwoPort senTemIn_p2(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    transferHeat=true,
    tauHeaTra=tauHeaTra) "Temperature sensor"

  Modelica.Blocks.Logical.Switch switch
    "Decide if mass flow rate is below measurement noise threshold or not"
  Modelica.Blocks.Sources.RealExpression m_flow_zero(y=0)
    "Default value if mass flow rate is below measurement noise threshold"
  Modelica.Blocks.Logical.LessThreshold lessThreshold(threshold=-0.001)
    "Measurement noise threshold"
  Modelica.Blocks.Logical.Switch switch1
    "Decide if mass flow rate is below measurement noise threshold or not"
  Fluid.Sources.MassFlowSource_T Point5(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1)
    "Bypass temperature sensor when flow rate is below measurement threshold"

  AixLib.Fluid.FixedResistances.Junction splPip1(
    redeclare package Medium = Medium,
    m_flow_nominal={pip1.m_flow_nominal,pip5.m_flow_nominal,pip4.m_flow_nominal},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal(each displayUnit="Pa") = {0,0,0},
    portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving)
    "Splitter coming out of pip1"
  AixLib.Fluid.FixedResistances.Junction splPip2(
    redeclare package Medium = Medium,
    m_flow_nominal={pip5.m_flow_nominal,pip2.m_flow_nominal,pip3.m_flow_nominal},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal(each displayUnit="Pa") = {0,0,0},
    portFlowDirection_1=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Entering,
    portFlowDirection_2=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    portFlowDirection_3=if allowFlowReversal then Modelica.Fluid.Types.PortFlowDirection.Bidirectional
         else Modelica.Fluid.Types.PortFlowDirection.Leaving)
    "Splitter coming out of pip5"
equation
  connect(m_flow_p3.y, Point3.m_flow_in)
  connect(Point2.m_flow_in, m_flow_p2.y)
  connect(T_p1.y, Point1.T_in)
  connect(DataReader.y[5], Point1.m_flow_in)
  connect(DataReader.y[9], prescribedTemperature.T)
  connect(pip4.heatPort, pip1.heatPort)
  connect(pip1.heatPort, pip0.heatPort)
  connect(pip1.heatPort, pip2.heatPort)
  connect(pip5.heatPort, pip2.heatPort)
  connect(pip3.heatPort, pip2.heatPort)
  connect(prescribedTemperature.port, pip0.heatPort)
  connect(senTem_p2.port_b, Point2.ports[1])
  connect(Point3.ports[1], senTem_p3.port_b)
  connect(senTem_p4.port_b, Point4.ports[1])
  connect(Point1.ports[1], senTem_p1.port_b)
  connect(senTem_p1.port_a, pip0.port_a)
  connect(switch.u1, m_flow_p4.y)
  connect(m_flow_zero.y, switch.u3)
  connect(switch.y, Point4.m_flow_in)
  connect(switch.u2, lessThreshold.y)
  connect(lessThreshold.u, m_flow_p4.y)
  connect(pip1.port_a, pip0.port_b)
  connect(pip4.port_b, senTem_p4.port_a)
  connect(Point5.ports[1], pip4.port_b)
  connect(senTemIn_p2.port_a, pip2.port_a)
  connect(pip2.port_b, senTem_p2.port_a)
  connect(pip3.port_b, senTem_p3.port_a)
  connect(ExcludedBranch.ports[1], pip0.port_b)
  connect(switch1.y, Point5.m_flow_in)
  connect(m_flow_p4.y, switch1.u3)
  connect(m_flow_zero.y, switch1.u1)
  connect(lessThreshold.y, switch1.u2)
  connect(pip5.port_a, splPip1.port_2)
  connect(pip1.port_b, splPip1.port_1)
  connect(splPip1.port_3, pip4.port_a)
  connect(senTemIn_p2.port_b, splPip2.port_2)
  connect(pip5.port_b, splPip2.port_1)
  connect(pip3.port_a, splPip2.port_3)
end PlugFlowAIT;


within AixLib.Fluid.FixedResistances.Validation.PlugFlowPipes;
model PlugFlowULg "Validation against data from Université de Liège"
  extends Modelica.Icons.Example;
  package Medium = AixLib.Media.Water;

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=1
    "Nominal mass flow rate, used for regularization near zero flow";
  parameter Modelica.Units.SI.Temperature T_start_in=pipeDataULg.T_start_in +
      273.15 "Initial temperature at pipe inlet";
  parameter Modelica.Units.SI.Temperature T_start_out=pipeDataULg.T_start_out
       + 273.15 "Initial temperature at pipe outlet";
  parameter Modelica.Units.SI.SpecificHeatCapacity cp_default=
      Medium.specificHeatCapacityCp(state=sta_default)
    "Heat capacity of medium";
  parameter Medium.ThermodynamicState sta_default=Medium.setState_pTX(
      T=Medium.T_default,
      p=Medium.p_default,
      X=Medium.X_default) "Default medium state";

  Fluid.Sources.MassFlowSource_T WaterCityNetwork(
    redeclare package Medium = Medium,
    m_flow=1.245,
    use_m_flow_in=true,
    nPorts=1) "Mass flow source"
  Fluid.HeatExchangers.Heater_T Boiler(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    dp_nominal=0) "Boiler with adjustable outlet temperature"
  Fluid.Sources.Boundary_pT Sewer1(
    redeclare package Medium = Medium,
    nPorts=1) "Mass flow sink"
  Fluid.Sensors.TemperatureTwoPort senTem_out(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    tau=0,
    T_start=T_start_out) "Temperature sensor"
  Fluid.Sensors.TemperatureTwoPort senTem_in(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    tau=0,
    T_start=T_start_in) "Temperature sensor"
  Modelica.Blocks.Sources.CombiTimeTable DataReader(
    tableOnFile=true,
    tableName="dat",
    fileName=pipeDataULg.filNam,
    columns=2:pipeDataULg.nCol,
    extrapolation=Modelica.Blocks.Types.Extrapolation.HoldLastPoint)
    "Measurement data"

  Modelica.Blocks.Math.UnitConversions.From_degC Tout
    "Ambient temperature in degrees"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature TBou(T=295.15)
    "Fixed boundary condition"
  Modelica.Blocks.Math.UnitConversions.From_degC Tin
    "Input temperature into pipe"

  replaceable Data.PipeDataULg151202 pipeDataULg constrainedby
    Data.BaseClasses.PipeDataULg
    "Measurement dataset from ULg (use Change Class... to choose from different experiments)"
  Modelica.Blocks.Math.Gain gain(k=1)
    "Gain to test variations of mass flow rate within measurement uncertainty "
  PlugFlowPipe pipe(
    redeclare package Medium = Medium,
    dh=0.05248,
    length=39,
    dIns(displayUnit="mm") = 0.013,
    kIns=0.04,
    m_flow_nominal=m_flow_nominal,
    thickness=3.9e-3,
    T_start_out=T_start_out,
    T_start_in=T_start_in,
    R=((1/(2*pipe.kIns)*log((0.0603/2 + pipe.dIns)/(0.0603/2))) + 1/(5*(0.0603
         + 2*pipe.dIns)))/Modelica.Constants.pi,
    initDelay=true,
    m_flow_start=pipeDataULg.m_flowIni,
    cPip=500,
    rhoPip=8000) "Pipe"
  Fluid.Sensors.EnthalpyFlowRate senEntOut(redeclare package Medium = Medium,
      m_flow_nominal=m_flow_nominal) "Outlet enthalpy sensor"
  Modelica.Blocks.Math.Add heatLossSim(k1=-1)
    "Difference between inflowing and outflowing enthalpy streams"
  Modelica.Blocks.Continuous.Integrator eneLosInt "Integrate model error"
  Fluid.Sensors.EnthalpyFlowRate senEntIn(redeclare package Medium = Medium,
      m_flow_nominal=m_flow_nominal) "Inlet enthalpy sensor"
  Modelica.Blocks.Math.Add delT(k2=-1)
    "Temperature difference between in- and outlet"
  Modelica.Blocks.Math.Product heaLosMea
    "Heat loss from measurement (mflow*cp*DeltaT)"
  Modelica.Blocks.Math.Gain gain3(k=cp_default) "Specific heat of water"
  Modelica.Blocks.Math.Feedback heaLosDiff
    "Difference between simulated and measurement enthalpy flow difference"
  Modelica.Blocks.Sources.Constant Tamb(k=273 + 18)
    "Ambient temperature in Kelvin";
equation
  connect(DataReader.y[3], Tout.u)
  connect(DataReader.y[5], Tin.u)
  connect(DataReader.y[1], gain.u)
  connect(senTem_in.port_a, Boiler.port_b)
  connect(Boiler.port_a, WaterCityNetwork.ports[1])
  connect(gain.y, WaterCityNetwork.m_flow_in)
  connect(Tin.y, Boiler.TSet)
  connect(Sewer1.ports[1], senTem_out.port_b)
  connect(senTem_out.port_a, senEntOut.port_b)
  connect(senEntOut.port_a, pipe.port_b)
  connect(pipe.port_a, senEntIn.port_b)
  connect(senTem_in.port_b, senEntIn.port_a)
  connect(TBou.port, pipe.heatPort)
  connect(gain.y, gain3.u)
  connect(heaLosMea.y, heaLosDiff.u2)
  connect(heatLossSim.y, heaLosDiff.u1)
  connect(heaLosDiff.y, eneLosInt.u)
  connect(delT.u1, Tin.y)
  connect(Tout.y, delT.u2)
  connect(heaLosMea.u1, gain3.y)
  connect(heaLosMea.u2, delT.y)
  connect(heatLossSim.u2, senEntIn.H_flow)
  connect(heatLossSim.u1, senEntOut.H_flow)
end PlugFlowULg;


within AixLib.Fluid.FixedResistances.Validation.PlugFlowPipes;
model TransportWaterAir
  "Validation model, one having water and the other air"
  extends Modelica.Icons.Example;
  package MediumW = AixLib.Media.Water "Medium in the pipe";
  package MediumA = AixLib.Media.Air(extraPropertiesNames={"CO2"})
   "Medium in the duct";

  parameter Modelica.Units.SI.Length length=20 "Pipe length";

  Modelica.Blocks.Sources.Step Tin(
    startTime=100,
    height=10,
    offset=273.15 + 20)
                   "Step input"
  Sources.Boundary_pT sin(
    redeclare package Medium = MediumW,
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325) "Pressure boundary condition"
  AixLib.Fluid.FixedResistances.PlugFlowPipe pip(
    redeclare package Medium = MediumW,
    dIns=0.05,
    kIns=0.028,
    m_flow_nominal=1,
    cPip=500,
    thickness=0.0032,
    initDelay=true,
    m_flow_start=1,
    rhoPip=8000,
    length=length,
    T_start_in=293.15,
    T_start_out=293.15) "Pipe"
  AixLib.Fluid.Sources.MassFlowSource_T sou(
    nPorts=1,
    redeclare package Medium = MediumW,
    use_T_in=true,
    m_flow=1) "Flow source"

  AixLib.Fluid.Sensors.TemperatureTwoPort senTemOutW(
    redeclare package Medium = MediumW,
    m_flow_nominal=1,
    tau=0,
    T_start=323.15) "Temperature sensor"
  AixLib.Fluid.Sensors.TemperatureTwoPort senTemIn(
    redeclare package Medium = MediumW,
    m_flow_nominal=1,
    tau=0,
    T_start=323.15) "Temperature sensor"
  Sources.Boundary_pT sin1(
    T=273.15 + 10,
    nPorts=1,
    p(displayUnit="Pa") = 101325,
    redeclare package Medium = MediumA)
    "Pressure boundary condition"
  PlugFlowPipe duc(
    dIns=0.05,
    kIns=0.028,
    m_flow_nominal=1,
    cPip=500,
    thickness=0.0032,
    initDelay=true,
    m_flow_start=1,
    rhoPip=8000,
    redeclare package Medium = MediumA,
    length=length,
    T_start_in=293.15,
    T_start_out=293.15) "Duct"
  Sources.MassFlowSource_T sou1(
    nPorts=1,
    use_T_in=true,
    redeclare package Medium = MediumA,
    use_X_in=true,
    use_C_in=true,
    m_flow=1)      "Flow source"
  Sensors.TemperatureTwoPort senTemOutA(
    m_flow_nominal=1,
    tau=0,
    redeclare package Medium = MediumA,
    T_start=323.15)
    "Temperature sensor"
  Sensors.TemperatureTwoPort senTemIn1(
    m_flow_nominal=1,
    tau=0,
    T_start=323.15,
    redeclare package Medium = MediumA)
    "Temperature sensor"
  Modelica.Blocks.Sources.Step XiIn[2](
    each startTime=100,
    height={0.01, -0.01},
    offset={0.01,0.99}) "Step input"
  Modelica.Blocks.Sources.Step CIn[1](
    each startTime=100,
    each height=0.01,
    each offset=1E-3) "Step input"
equation
  connect(Tin.y, sou.T_in)
  connect(pip.port_b, senTemOutW.port_a)
  connect(senTemOutW.port_b, sin.ports[1])
  connect(sou.ports[1], senTemIn.port_a)
  connect(senTemIn.port_b, pip.port_a)
  connect(duc.port_b,senTemOutA. port_a)
  connect(senTemOutA.port_b, sin1.ports[1])
  connect(sou1.ports[1], senTemIn1.port_a)
  connect(senTemIn1.port_b, duc.port_a)
  connect(sou1.X_in, XiIn.y)
  connect(sou1.C_in, CIn.y)
  connect(Tin.y, sou1.T_in)
end TransportWaterAir;


within AixLib.Fluid.FixedResistances.Validation.PlugFlowPipes;
package Data "Experimental data for verification of pipe models"
end Data;


Example to check pipe data records. Model used to visualize and check data of district heating networks

within AixLib.Fluid.FixedResistances.Validation.PlugFlowPipes.Data;
model TestData "Example to check pipe data records"
extends Modelica.Icons.Example;
replaceable PipeDataAIT151218 pipeDataToBeRead constrainedby
    BaseClasses.PipeDataBaseDefinition "Measurement dataset from AIT"
    Modelica.Blocks.Sources.CombiTimeTable combiTimeTable(
    tableOnFile=true,
    tableName="dat",
    fileName=pipeDataToBeRead.filNam,
    columns=2:pipeDataToBeRead.nCol)
equation
end TestData;


BaseClasses for data records

within AixLib.Fluid.FixedResistances.Validation.PlugFlowPipes.Data;
package BaseClasses "BaseClasses for data records"
extends Modelica.Icons.BasesPackage;
end BaseClasses;


within AixLib.Fluid.FMI;
block FlowSplitter_u "Model of a flow splitter that can be exported as an FMU"
  extends Modelica.Blocks.Icons.Block;

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

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal[nout](each min=0)
    "Nominal mass flow rate for each outlet";
  parameter Boolean allowFlowReversal = true
    "= true to allow flow reversal, false restricts to design direction (inlet -> outlet)"

  parameter Integer nout(min=1) "Number of outlets";

 parameter Boolean use_p_in=true
    "= true to use a pressure from connector, false to output Medium.p_default"

  Interfaces.Inlet inlet(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final use_p_in=use_p_in) "Fluid inlet"

  Interfaces.Outlet outlet[nout](
    redeclare each final package Medium = Medium,
    each final allowFlowReversal=allowFlowReversal,
    each final use_p_in=use_p_in) "Fluid outlet"
  Modelica.Blocks.Interfaces.RealInput u[nout](
    each unit="1") "Control signal for the mass flow rates"
protected
  final parameter Modelica.Units.SI.MassFlowRate mAve_flow_nominal=sum(
      m_flow_nominal)/nout "Average nominal mass flow rate";
protected
  input AixLib.Fluid.FMI.Interfaces.FluidProperties bacPro_internal(
    redeclare final package Medium = Medium)
    "Internal connector for fluid properties for back flow";
  output AixLib.Fluid.FMI.Interfaces.MassFractionConnector X_w_out_internal = 0
    "Internal connector for mass fraction of backward flow properties";

initial equation
  for i in 1:nout loop
    assert(m_flow_nominal[i] > 0,
      "Nominal mass flow rate must be bigger than zero.");
  end for;
equation
  for i in 1:nout loop
    assert(u[i] >= 0, "Control signal must be non-negative.");
    // Dymola 2015 FD01 (on Linux 64) does not automatically
    // remove the conditional equation below. We thus have to manually check
    // if use_p_in is true before connecting the inlet and outlet pressures.
    if use_p_in then
      connect(inlet.p, outlet[i].p);
    end if;
    outlet[i].m_flow = u[i]*m_flow_nominal[i];
    connect(outlet[i].forward, inlet.forward);
  end for;

  // As reverse flow is not supported, we assign
  // default values for the inlet.backward properties
  bacPro_internal.T = Medium.T_default;
  connect(bacPro_internal.X_w, X_w_out_internal);
  bacPro_internal.C  = zeros(Medium.nC);

  // Conditional connector
  connect(bacPro_internal, inlet.backward);
end FlowSplitter_u;


within AixLib.Fluid;
package FMI "Package with base classes that facilitate exporting models as an FMU"
  extends Modelica.Icons.Package;
end FMI;


within AixLib.Fluid.FMI;
model Sink_T
  "Model of a sink with temperature for reverse flow as an input that can be exported as an FMU"
  extends Modelica.Blocks.Icons.Block;
  replaceable package Medium =
    Modelica.Media.Interfaces.PartialMedium "Medium in the component"

  parameter Boolean use_p_in = true
    "= true to use a pressure from connector, false to output Medium.p_default"

  parameter Boolean allowFlowReversal = true
    "= true to allow flow reversal, false restricts to design direction (inlet -> outlet)"

  Modelica.Blocks.Interfaces.RealInput T_in(unit="K",
                                            displayUnit="degC",
                                            min=0)
    "Prescribed boundary temperature"
  Modelica.Blocks.Interfaces.RealInput X_w_in(unit="1")
    if Medium.nXi > 0 "Prescribed boundary composition"

  Modelica.Blocks.Interfaces.RealInput C_in[Medium.nC]
    "Prescribed boundary composition"

  Interfaces.Inlet inlet(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final use_p_in=use_p_in) "Fluid port"
  AixLib.Fluid.FMI.Interfaces.PressureOutput p
  if use_p_in "Pressure"
protected
  input AixLib.Fluid.FMI.Interfaces.FluidProperties bacPro_internal(
    redeclare final package Medium = Medium)
    "Internal connector for fluid properties for back flow";
  AixLib.Fluid.FMI.Interfaces.PressureOutput p_in_internal
    "Internal connector for pressure";
  output AixLib.Fluid.FMI.Interfaces.MassFractionConnector X_w_in_internal
    "Internal connector for mass fraction of forward flow properties";

equation
 // Conditional connector for flow reversal
  connect(inlet.backward, bacPro_internal);
  connect(bacPro_internal.X_w, X_w_in_internal);
  if allowFlowReversal and Medium.nXi > 0 then
    connect(X_w_in_internal, X_w_in);
  else
    X_w_in_internal = 0;
  end if;

  if allowFlowReversal then
    bacPro_internal.T  = T_in;
    bacPro_internal.C  = C_in;
  else
    bacPro_internal.T = Medium.T_default;
    bacPro_internal.C  = fill(0, Medium.nC);
  end if;

  // Propagate pressure to output signal connector
  // using conditional connectors
  if use_p_in then
    connect(inlet.p, p_in_internal);
  else
    p_in_internal = Medium.p_default;
  end if;
  connect(p, p_in_internal);
end Sink_T;


within AixLib.Fluid.FMI;
model Source_T
  "Model of a boundary with mass flow rate, pressure and temperature as an input that can be exported as an FMU"
  extends Modelica.Blocks.Icons.Block;
  replaceable package Medium =
    Modelica.Media.Interfaces.PartialMedium "Medium in the component"

  parameter Boolean allowFlowReversal = true
    "= true to allow flow reversal, false restricts to design direction (inlet -> outlet)"

  parameter Boolean use_p_in = true
    "= true to use a pressure from connector, false to output Medium.p_default"

  Modelica.Blocks.Interfaces.RealInput m_flow_in(unit="kg/s")
    "Prescribed mass flow source"

  AixLib.Fluid.FMI.Interfaces.PressureInput p_in
    if use_p_in "Prescribed boundary pressure"
  Modelica.Blocks.Interfaces.RealInput T_in(unit="K",
                                            displayUnit="degC",
                                            min=0)
    "Prescribed boundary temperature"
  Modelica.Blocks.Interfaces.RealInput X_w_in(unit="1")
    if Medium.nXi > 0 "Prescribed boundary composition"

  Modelica.Blocks.Interfaces.RealInput C_in[Medium.nC]
    "Prescribed boundary composition"

  Interfaces.Outlet outlet(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final use_p_in=use_p_in) "Fluid port"
protected
  AixLib.Fluid.FMI.Interfaces.PressureOutput p_in_internal
    "Internal connector for pressure";
  input AixLib.Fluid.FMI.Interfaces.MassFractionConnector X_w_in_internal
    "Internal connector for mass fraction of forward flow properties";
initial equation
   assert(Medium.nXi < 2,
   "The medium must have zero or one independent mass fraction Medium.nXi.");
equation
   // Conditional connect statements for pressure
   if use_p_in then
     connect(p_in, p_in_internal);
   else
     p_in_internal = Medium.p_default;
   end if;
   connect(outlet.p, p_in_internal);

  // Conditional connectors for mass fraction
  if Medium.nXi > 0 then
    connect(X_w_in_internal, X_w_in);
  else
    X_w_in_internal = 0;
  end if;
  connect(outlet.forward.X_w, X_w_in_internal);

  outlet.m_flow = m_flow_in;

  outlet.forward.T  = T_in;
  outlet.forward.C  = C_in;
end Source_T;


User's Guide

within AixLib.Fluid.FMI;
package UsersGuide "User's Guide"
  extends Modelica.Icons.Information;
end UsersGuide;


within AixLib.Fluid.FMI.Adaptors;
model HVAC
  "Adaptor for connecting an HVAC system to signal ports which then can be exposed at an FMI interface"

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

  // Don't use

  Interfaces.Outlet fluPor[nPorts](
    redeclare each final package Medium = Medium,
    each final allowFlowReversal=true,
    each final use_p_in=false) "Fluid connector"

  Modelica.Fluid.Interfaces.FluidPorts_b ports[nPorts](
    redeclare each final package Medium = Medium)

  Modelica.Blocks.Interfaces.RealOutput TAirZon[nPorts](
    each final unit="K",
    each displayUnit="degC")
    "Temperature of the backward flowing medium in the connector outlet"
  Modelica.Blocks.Interfaces.RealOutput X_wZon[nPorts](
    each final unit="kg/kg")
    if Medium.nXi > 0
    "Water mass fraction per total air mass of the backward flowing medium in the connector outlet"
  Modelica.Blocks.Interfaces.RealOutput CZon[nPorts, Medium.nC](
    final quantity=fill(Medium.extraPropertiesNames, nPorts))
    "Trace substances of the backward flowing medium in the connector outlet"

protected
  Sources.MassFlowSource_T bou(
    final nPorts=nPorts,
    redeclare final package Medium = Medium,
    final use_m_flow_in=false,
    final use_T_in=true,
    final use_X_in=Medium.nXi > 0,
    final use_C_in=Medium.nC > 0,
    final m_flow=0) "Boundary conditions for HVAC system"

  AixLib.Fluid.FMI.Conversion.AirToOutlet con[nPorts](
      redeclare each final package Medium = Medium,
      each final allowFlowReversal=true)
    "Converter between the different connectors"

  Sensors.MassFlowRate senMasFlo[nPorts](
    redeclare each final package Medium = Medium,
    each allowFlowReversal=true) "Mass flow rate sensor"

  AixLib.Fluid.FMI.BaseClasses.X_w_toX x_w_toX(
    redeclare final package Medium = Medium)
    if Medium.nXi > 0 "Conversion from X_w to X"

  Modelica.Blocks.Sources.RealExpression hSup[nPorts](
    final y={inStream(ports[i].h_outflow) for i in 1:nPorts})
    "Supply air specific enthalpy"

  RealVectorExpression XiSup[nPorts](
    each final n = Medium.nXi,
    final y={inStream(ports[i].Xi_outflow) for i in 1:nPorts})
    if Medium.nXi > 0 "Water vapor concentration of supply air"

  RealVectorExpression CSup[nPorts](
    each final n=Medium.nC,
    final y={inStream(ports[i].C_outflow) for i in 1:nPorts})
    if Medium.nC > 0 "Trace substance concentration of supply air"

  ///////////////////////////////////////////////////////////////////////////
  // Internal blocks
  block RealVectorExpression
    "Set vector output signal to a time varying vector Real expression"
    parameter Integer n "Dimension of output signal";
    Modelica.Blocks.Interfaces.RealOutput[n] y "Value of Real output"

  end RealVectorExpression;

initial equation
   assert(Medium.nXi < 2,
   "The medium must have zero or one independent mass fraction Medium.nXi.");
equation

  connect(con.outlet, fluPor)
  connect(senMasFlo.m_flow, con.m_flow)
  connect(hSup.y, con.h)
  for i in 1:nPorts loop
    connect(XiSup[i].y, con[i].Xi)
    connect(CSup[i].y, con[i].C)
  end for;
  connect(senMasFlo.port_b, bou.ports)
  connect(ports, senMasFlo.port_a)
  connect(con[1].TAirZon, bou.T_in)
  connect(con[1].X_wZon, x_w_toX.X_w)
  connect(x_w_toX.X, bou.X_in)
  connect(con[1].CZon, bou.C_in)
  connect(con.TAirZon, TAirZon)
  connect(con.X_wZon, X_wZon)
  connect(con.CZon, CZon)
end HVAC;


within AixLib.Fluid.FMI.Adaptors;
model Inlet "Adaptor for connecting a fluid inlet to the FMI interface"

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

  parameter Boolean allowFlowReversal = true
    "= true to allow flow reversal, false restricts to design direction (inlet -> outlet)"

  parameter Boolean use_p_in = true
    "= true to use a pressure from connector, false to output Medium.p_default"

  AixLib.Fluid.FMI.Interfaces.Inlet inlet(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final use_p_in=use_p_in) "Fluid inlet"

  Modelica.Fluid.Interfaces.FluidPort_b port_b(
    redeclare final package Medium=Medium) "Fluid port"
  AixLib.Fluid.FMI.Interfaces.PressureOutput p
  if use_p_in "Pressure"
protected
  input AixLib.Fluid.FMI.Interfaces.FluidProperties bacPro_internal(
    redeclare final package Medium = Medium)
    "Internal connector for fluid properties for back flow";
  AixLib.Fluid.FMI.Interfaces.PressureOutput p_in_internal
    "Internal connector for pressure";
  output AixLib.Fluid.FMI.Interfaces.MassFractionConnector X_w_in_internal
    "Internal connector for mass fraction of forward flow properties";
  output AixLib.Fluid.FMI.Interfaces.MassFractionConnector X_w_out_internal
    "Internal connector for mass fraction of backward flow properties";
initial equation
   assert(Medium.nXi < 2,
   "The medium must have zero or one independent mass fraction Medium.nXi.");
equation
  // To locally balance the model, the pressure is only imposed at the
  // outlet model.
  // The sign is negative because inlet.m_flow > 0
  // means that fluid flows out of this component
  -port_b.m_flow     = inlet.m_flow;

  port_b.h_outflow  = Medium.specificEnthalpy_pTX(
                        p = p_in_internal,
                        T = inlet.forward.T,
                        X = if Medium.nXi == 1 then cat(1, {X_w_in_internal}, {1-X_w_in_internal}) else zeros(Medium.nX));

  port_b.C_outflow  = inlet.forward.C;

  // Conditional connector for mass fraction for forward flow
  if Medium.nXi == 0 then
    X_w_in_internal = 0;
  else
    connect(X_w_in_internal, inlet.forward.X_w);
  end if;
  port_b.Xi_outflow = fill(X_w_in_internal, Medium.nXi);

  // Conditional connector for flow reversal
  connect(inlet.backward, bacPro_internal);

  // Mass fraction for reverse flow
  X_w_out_internal = if Medium.nXi > 0 and allowFlowReversal then inStream(port_b.Xi_outflow[1]) else 0;
  connect(bacPro_internal.X_w, X_w_out_internal);

  if allowFlowReversal then
    bacPro_internal.T  = Medium.temperature_phX(
                           p = p_in_internal,
                           h = inStream(port_b.h_outflow),
                           X = cat(1, inStream(port_b.Xi_outflow), {1-sum(inStream(port_b.Xi_outflow))}));
    bacPro_internal.C  = inStream(port_b.C_outflow);
  else
    bacPro_internal.T  = Medium.T_default;
    bacPro_internal.C  = fill(0, Medium.nC);
  end if;

  // Conditional connectors for pressure
  if use_p_in then
  connect(inlet.p, p_in_internal);
  else
    p_in_internal = Medium.p_default;
  end if;
  connect(p, p_in_internal);
end Inlet;


within AixLib.Fluid.FMI.Adaptors;
model Outlet "Adaptor for connecting a fluid outlet to the FMI interface"

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

  parameter Boolean allowFlowReversal = true
    "= true to allow flow reversal, false restricts to design direction (inlet -> outlet)"

  parameter Boolean use_p_in = true
    "= true to use a pressure from connector, false to output Medium.p_default"

  AixLib.Fluid.FMI.Interfaces.Outlet outlet(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final use_p_in=use_p_in) "Fluid outlet"

  Modelica.Fluid.Interfaces.FluidPort_a port_a(
    redeclare final package Medium=Medium) "Fluid port"
  AixLib.Fluid.FMI.Interfaces.PressureInput p
    if use_p_in "Pressure to be sent to outlet"
protected
  output AixLib.Fluid.FMI.Interfaces.FluidProperties bacPro_internal(
    redeclare final package Medium = Medium)
    "Internal connector for fluid properties for back flow";
  AixLib.Fluid.FMI.Interfaces.PressureOutput p_in_internal
    "Internal connector for pressure";

  input AixLib.Fluid.FMI.Interfaces.MassFractionConnector X_w_in_internal
    "Internal connector for mass fraction of forward flow properties";
  output AixLib.Fluid.FMI.Interfaces.MassFractionConnector X_w_out_internal
    "Internal connector for mass fraction of backward flow properties";
initial equation
   assert(Medium.nXi < 2,
   "The medium must have zero or one independent mass fraction Medium.nXi.");
equation
  port_a.m_flow = outlet.m_flow;

  outlet.forward.T = Medium.temperature_phX(
    p = p_in_internal,
    h = inStream(port_a.h_outflow),
    X = cat(1, inStream(port_a.Xi_outflow), {1-sum(inStream(port_a.Xi_outflow))}));

  inStream(port_a.C_outflow)  = outlet.forward.C;

  // Mass fraction for forward flow
  X_w_in_internal = if Medium.nXi > 0 then inStream(port_a.Xi_outflow[1]) else 0;
  connect(outlet.forward.X_w, X_w_in_internal);

  // Conditional connector for mass fraction for backward flow
  if Medium.nXi > 0 and allowFlowReversal then
    connect(X_w_out_internal, outlet.backward.X_w);
  else
    X_w_out_internal = 0;
  end if;
  port_a.Xi_outflow = fill(X_w_out_internal, Medium.nXi);

  // Conditional connector for flow reversal
  connect(outlet.backward, bacPro_internal);
  if not allowFlowReversal then
    bacPro_internal.T  = Medium.T_default;
    bacPro_internal.C  = fill(0, Medium.nC);
    if Medium.nXi > 0 then
      // This test for nXi is needed for AixLib.Fluid.FMI.Validation.HeaterFan_noReverseFlow
      // to work with AixLib.Media.Water
      connect(bacPro_internal.X_w, X_w_out_internal);
    end if;
  end if;
  bacPro_internal.T  = Medium.temperature_phX(
    p = p_in_internal,
    h = port_a.h_outflow,
    X = cat(1, port_a.Xi_outflow, {1-sum(port_a.Xi_outflow)}));
  bacPro_internal.C  = port_a.C_outflow;

  // Conditional connectors for pressure
  if use_p_in then
    connect(outlet.p, p_in_internal);
  else
    p_in_internal = Medium.p_default;
  end if;
  connect(p, p_in_internal);
  port_a.p = p_in_internal;
end Outlet;


within AixLib.Fluid.FMI;
package Adaptors "Package with adaptors to connect models with fluid ports and models with signal ports"
  extends Modelica.Icons.Package;
end Adaptors;


within AixLib.Fluid.FMI.Adaptors;
model ThermalZone
  "Adaptor for connecting a thermal zone to signal ports which then can be exposed at an FMI interface"

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

  // Don't use

  Interfaces.Inlet fluPor[nPorts](
    redeclare each final package Medium = Medium,
    each final allowFlowReversal=true,
    each final use_p_in=false) "Fluid connector"

  Modelica.Fluid.Interfaces.FluidPorts_b ports[nPorts](
    redeclare each final package Medium = Medium)

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heaPorAir
    "Heat port for sensible heat input"

protected
  x_i_toX_w x_i_toX(
    redeclare final package Medium = Medium)
 if Medium.nXi > 0 "Conversion from x_i to X_w"

  RealVectorExpression XiSup(
    final n=Medium.nXi,
    final y=inStream(ports[1].Xi_outflow))
    if Medium.nXi > 0
      "Water vapor concentration of supply air"

  RealVectorExpression CSup(
    final n=Medium.nC,
    final y=inStream(ports[1].C_outflow))
 if Medium.nC > 0 "Trace substance concentration of supply air"

  Sources.MassFlowSource_T bou[nPorts](
    each final nPorts=1,
    redeclare each final package Medium = Medium,
    each final use_T_in=true,
    each final use_C_in=Medium.nC > 0,
    each final use_X_in=Medium.nXi > 0,
    each use_m_flow_in=true) "Mass flow source"

  Conversion.InletToAir con[nPorts](redeclare each final package Medium =
        Medium) "Connector between FMI signals and real input and real outputs"

  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor senTemAir
    "Room air temperature sensor"

  BaseClasses.X_w_toX x_w_toX[nPorts](redeclare final package Medium = Medium)
    if Medium.nXi > 0 "Conversion from X_w to X"

  Modelica.Blocks.Math.MultiSum multiSum(final nu=nPorts, final k=fill(1,
        nPorts)) "Sum of air mass flow rates"

  AixLib.Utilities.Diagnostics.AssertEquality assEqu(
    message="\"Mass flow rate does not balance. The sum needs to be zero.",
      threShold=1E-4)
    "Tests whether the mass flow rates balance to zero"
  Modelica.Blocks.Sources.Constant const(final k=0) "Outputs zero"

  ///////////////////////////////////////////////////////////////////////////
  // Internal blocks
  block RealVectorExpression
    "Set vector output signal to a time varying vector Real expression"
    parameter Integer n "Dimension of output signal";
    Modelica.Blocks.Interfaces.RealOutput[n] y "Value of Real output"
  end RealVectorExpression;

  block x_i_toX_w "Conversion from Xi to X"
    extends Modelica.Blocks.Icons.Block;

    replaceable package Medium =
      Modelica.Media.Interfaces.PartialMedium "Medium model within the source"
    Modelica.Blocks.Interfaces.RealInput Xi[Medium.nXi](each final unit="kg/kg")
   if Medium.nXi > 0 "Water vapor concentration in kg/kg total air"

    Modelica.Blocks.Interfaces.RealOutput X_w(
      final unit="kg/kg") "Water vapor concentration in kg/kg total air"
  protected
    Modelica.Blocks.Interfaces.RealInput Xi_internal[Medium.nXi](
      each final unit = "kg/kg")
      "Internal connector for water vapor concentration in kg/kg total air";

    Modelica.Blocks.Interfaces.RealInput X_w_internal(
      final unit = "kg/kg")
      "Internal connector for water vapor concentration in kg/kg total air";

  equation
  // Conditional connector
  connect(Xi_internal, Xi);
  if Medium.nXi == 0 then
    Xi_internal = zeros(Medium.nXi);
  end if;

  X_w_internal = sum(Xi_internal);
  connect( X_w, X_w_internal)
  end x_i_toX_w;

initial equation
   assert(Medium.nXi < 2,
   "The medium must have zero or one independent mass fraction Medium.nXi.");
equation

  for i in 1:nPorts loop
    connect(bou[i].ports[1], ports[i])
  end for;
  connect(con.inlet, fluPor)
  connect(con.X_w, x_w_toX.X_w)

  connect(x_w_toX.X, bou.X_in)
  connect(con.C, bou.C_in)
  connect(heaPorAir, senTemAir.port)
  connect(XiSup.y, x_i_toX.Xi)
  connect(con.T, bou.T_in)
  connect(con[1:nPorts].m_flow, multiSum.u[1:nPorts])
  connect(multiSum.y, assEqu.u2)
  connect(const.y, assEqu.u1)
  for i in 1:nPorts loop
  connect(senTemAir.T, con[i].TAirZon)
  if Medium.nXi > 0 then
    connect(x_i_toX.X_w, con[i].X_wZon)
  end if;
  connect(CSup.y, con[i].CZon)
  end for;
  connect(bou.m_flow_in, con.m_flow)
end ThermalZone;


within AixLib.Fluid.FMI.Adaptors;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


within AixLib.Fluid.FMI.Adaptors.Examples;
model ThermalZoneHVACNoExhaust
  "Example of a thermal zone and an HVAC system both exposed using the FMI adaptor"
  extends Modelica.Icons.Example;

  replaceable package MediumA = AixLib.Media.Air "Medium for air";

  AixLib.Fluid.FMI.Adaptors.HVAC hvacAda(
    redeclare final package Medium=MediumA, nPorts=2)
    "Adaptor for an HVAC system that is exposed through an FMI interface"

  parameter Modelica.Units.SI.HeatFlowRate Q_flow_nominal=30*6*6
    "Nominal heat loss of the room";

  parameter Modelica.Units.SI.Volume VRoo=6*6*2.7 "Room volume";

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=VRoo*2*1.2/3600
    "Nominal mass flow rate";

  AixLib.Fluid.FMI.Adaptors.ThermalZone con(
    redeclare package Medium = MediumA,
    nPorts=2) "Adaptor for thermal zone"
  Modelica.Blocks.Sources.Pulse TSet(
    amplitude=4,
    period=86400,
    offset=273.15 + 16,
    startTime=7*3600) "Setpoint for room temperature"
  Controls.Continuous.LimPID conPI(
    k=1,
    yMax=1,
    yMin=0,
    Ti=120) "Controller"
  Movers.FlowControlled_m_flow mov(
    redeclare package Medium = MediumA,
    m_flow_nominal=m_flow_nominal,
    addPowerToMedium=false,
    nominalValuesDefineDefaultPressureCurve=true,
    dp_nominal=1200,
    inputType=AixLib.Fluid.Types.InputType.Constant,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    use_inputFilter=false) "Fan or pump"
  HeatExchangers.HeaterCooler_u
    hea(
    redeclare package Medium = MediumA,
    m_flow_nominal=m_flow_nominal,
    dp_nominal=1000,
    Q_flow_nominal=Q_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState) "Heater"

  Sources.Boundary_pT out(
    redeclare package Medium = MediumA,
    nPorts=2,
    use_T_in=true) "Pressure and temperature source for outdoor"
  HeatExchangers.ConstantEffectiveness hex(
    redeclare package Medium1 = MediumA,
    redeclare package Medium2 = MediumA,
    m1_flow_nominal=m_flow_nominal,
    m2_flow_nominal=m_flow_nominal,
    dp1_nominal=200,
    dp2_nominal=200) "Heat recovery"
  MixingVolumes.MixingVolume vol(
    redeclare package Medium = MediumA,
    mSenFac=3,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    V=VRoo,
    nPorts=2) "Room volume"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=
    Q_flow_nominal/20)
    "Thermal conductance with the ambient"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature TBou
    "Fixed temperature boundary condition"
  Modelica.Blocks.Sources.RealExpression TOutZon(
    y=273.15 + 16 - 5*cos(time/86400*2*Modelica.Constants.pi))
    "Outdoor temperature used for the thermal zone model"
  Modelica.Blocks.Sources.RealExpression TOutHVAC(
    y=273.15 + 16 - 5*cos(time/86400*2*Modelica.Constants.pi))
    "Outdoor temperature used for the HVAC model"
equation
  connect(mov.port_b,hea. port_a)
  connect(hex.port_b1,mov. port_a)
  connect(out.ports[1],hex. port_b2)
  connect(out.ports[2],hex. port_a1)
  connect(conPI.y, hea.u)
  connect(TBou.port,theCon. port_a)
  connect(vol.heatPort, theCon.port_b)
  connect(conPI.u_s, TSet.y)
  connect(TOutZon.y, TBou.T)
  connect(hvacAda.TAirZon[1], conPI.u_m)
  connect(con.ports[1], vol.ports[1])
  connect(vol.heatPort, con.heaPorAir)
  connect(con.ports[2], vol.ports[2])
  connect(hvacAda.fluPor, con.fluPor)
  connect(hea.port_b, hvacAda.ports[1])
  connect(hvacAda.ports[2], hex.port_a2)
  connect(TOutHVAC.y, out.T_in)
end ThermalZoneHVACNoExhaust;


within AixLib.Fluid.FMI.Adaptors.Examples;
model ThermalZoneHVACWithExhaust
  "Example of a thermal zone and an HVAC system both exposed using the FMI adaptor"
  extends AixLib.Fluid.FMI.Adaptors.Examples.ThermalZoneHVACNoExhaust(
    hvacAda(nPorts=3),
    out(nPorts=3),
    con(nPorts=3),
    vol(nPorts=3));

  Movers.FlowControlled_m_flow exh(
    redeclare package Medium = MediumA,
    addPowerToMedium=false,
    nominalValuesDefineDefaultPressureCurve=true,
    dp_nominal=1200,
    inputType=AixLib.Fluid.Types.InputType.Constant,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    use_inputFilter=false,
    m_flow_nominal=0.1*m_flow_nominal) "Constant air exhaust"
equation
  connect(hvacAda.ports[3], exh.port_a)
  connect(exh.port_b, out.ports[3])
  connect(con.ports[3], vol.ports[3])
end ThermalZoneHVACWithExhaust;


Conversion from h to T

within AixLib.Fluid.FMI.BaseClasses;
block hOut_toT "Conversion from h to T"
  extends Modelica.Blocks.Icons.Block;

  replaceable package Medium =
    Modelica.Media.Interfaces.PartialMedium "Medium in the component"
  Modelica.Blocks.Interfaces.RealInput h(final unit="J/kg") "Specific enthalpy"

  Modelica.Blocks.Interfaces.RealInput Xi[Medium.nXi](each final unit="kg/kg")
    if Medium.nXi > 0 "Water vapor concentration in kg/kg total air"

  Modelica.Blocks.Interfaces.RealOutput T(final unit="K",
                                            displayUnit="degC") "Temperature"
protected
  Modelica.Blocks.Interfaces.RealInput Xi_internal[Medium.nXi](
    each final unit = "kg/kg")
    "Internal connector for water vapor concentration in kg/kg total air";

equation
  // Conditional connectors
  connect(Xi_internal, Xi);
  if Medium.nXi == 0 then
    Xi_internal = zeros(Medium.nXi);
  end if;

 T = Medium.temperature_phX(
      p=Medium.p_default,
      h=h,
      X=Xi_internal);
end hOut_toT;


within AixLib.Fluid.FMI;
package BaseClasses "Package with base classes for AixLib.Fluid.FMI"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Conversion from Xi to X

within AixLib.Fluid.FMI.BaseClasses;
block X_w_toX "Conversion from Xi to X"
  extends Modelica.Blocks.Icons.Block;

  replaceable package Medium =
    Modelica.Media.Interfaces.PartialMedium "Medium in the component"
  Modelica.Blocks.Interfaces.RealInput X_w(final unit="kg/kg")
     if Medium.nXi > 0 "Water mass fraction per total air mass"
  Modelica.Blocks.Interfaces.RealOutput X[Medium.nX](
    each final unit="kg/kg",
    final quantity=Medium.substanceNames) "Prescribed fluid composition"
protected
  Modelica.Blocks.Interfaces.RealInput X_w_internal(final unit="kg/kg")
    "Internal connector for water mass fraction per total air mass";
equation
  // Conditional connector
  connect(X_w_internal, X_w);
  if Medium.nXi == 0 then
    X_w_internal = 0;
  end if;
  // Assign vector to output connector
 X = if Medium.nX == 1 then ones(Medium.nX) else cat(1, {X_w_internal}, {1-X_w_internal});
end X_w_toX;