Nominal water mass flow rate

within Buildings.Fluid.Interfaces.Examples;
model Humidifier_u
  extends Modelica.Icons.Example;

 package Medium = Buildings.Media.Air;
  parameter Modelica.Units.SI.MassFlowRate mWat_flow_nominal=0.001
    "Nominal water mass flow rate";
  Humidifier hea1(redeclare package Medium =
        Medium,
    m_flow_nominal=0.5,
    mWat_flow_nominal=mWat_flow_nominal,
    dp_nominal=50,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Heater and cooler"
  Modelica.Blocks.Sources.Constant TDb(k=293.15) "Drybulb temperature"
  Buildings.Fluid.Sources.Boundary_pT sou_1(
    redeclare package Medium = Medium,
    use_T_in=true,
    nPorts=4,
    p(displayUnit="Pa") = 101435,
    T=293.15)
  Buildings.Fluid.FixedResistances.PressureDrop res_11(
    redeclare package Medium = Medium,
    dp_nominal=5,
    m_flow_nominal=0.5)
  Buildings.Fluid.FixedResistances.PressureDrop res_12(
    redeclare package Medium = Medium,
    dp_nominal=5,
    m_flow_nominal=0.5)
  Buildings.Fluid.Sources.Boundary_pT sin_1(
    redeclare package Medium = Medium,
    use_p_in=true,
    T=288.15,
    nPorts=4)
    Modelica.Blocks.Sources.Constant POut(k=101325)
    Modelica.Blocks.Sources.Ramp u(
    duration=3600,
    startTime=0,
    height=1,
    offset=0) "Control signal"
  Humidifier hea2(
    redeclare package Medium = Medium,
    m_flow_nominal=0.5,
    mWat_flow_nominal=mWat_flow_nominal,
    dp_nominal=50,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Heater and cooler"
  Modelica.Blocks.Math.Gain gain(k=-1)
  Humidifier hea3(
    redeclare package Medium = Medium,
    m_flow_nominal=0.5,
    mWat_flow_nominal=mWat_flow_nominal,
    dp_nominal=50,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Heater and cooler"
  Buildings.Fluid.FixedResistances.PressureDrop res_2(
    redeclare package Medium = Medium,
    dp_nominal=5,
    m_flow_nominal=0.5)
  Buildings.Fluid.FixedResistances.PressureDrop res_3(
    redeclare package Medium = Medium,
    dp_nominal=5,
    m_flow_nominal=0.5)
  Humidifier hea4(
    redeclare package Medium = Medium,
    m_flow_nominal=0.5,
    mWat_flow_nominal=mWat_flow_nominal,
    dp_nominal=50,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Heater and cooler"
  Buildings.Fluid.FixedResistances.PressureDrop res_4(
    redeclare package Medium = Medium,
    dp_nominal=5,
    m_flow_nominal=0.5)
  Buildings.Fluid.MixingVolumes.MixingVolume mix1(
    redeclare package Medium = Medium,
    V=0.000001,
    nPorts=2,
    m_flow_nominal=0.5,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
  Modelica.Blocks.Math.Add che1(k2=-1)
  Modelica.Blocks.Sources.RealExpression y1(y=hea2.T_b.T)
  Modelica.Blocks.Sources.RealExpression y2(y=hea1.T_b.T)
  Modelica.Blocks.Math.Add che2(k2=-1)
  Modelica.Blocks.Sources.RealExpression y3(y=hea2.T_a.T)
  Modelica.Blocks.Sources.RealExpression y4(y=hea1.T_a.T)
  Modelica.Blocks.Math.Add che3(k2=-1)
  Modelica.Blocks.Sources.RealExpression y5(y=hea4.T_b.T)
  Modelica.Blocks.Sources.RealExpression y6(y=hea3.T_b.T)
  Modelica.Blocks.Math.Add che4(k2=-1)
  Modelica.Blocks.Sources.RealExpression y7(y=hea4.T_a.T)
  Modelica.Blocks.Sources.RealExpression y8(y=hea3.T_a.T)
  Humidifier hea5(redeclare package Medium =
        Medium,
    m_flow_nominal=0.5,
    mWat_flow_nominal=mWat_flow_nominal,
    dp_nominal=50,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Heater and cooler"
  Buildings.Fluid.FixedResistances.PressureDrop res_1(
    redeclare package Medium = Medium,
    dp_nominal=5,
    m_flow_nominal=0.5)
  Buildings.Fluid.FixedResistances.PressureDrop res_5(
    redeclare package Medium = Medium,
    dp_nominal=5,
    m_flow_nominal=0.5)
  Humidifier hea6(                               redeclare package Medium =
        Medium,
    m_flow_nominal=0.5,
    mWat_flow_nominal=mWat_flow_nominal,
    dp_nominal=50,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Heater and cooler"
  Humidifier hea7(redeclare package Medium =
        Medium,
    m_flow_nominal=0.5,
    mWat_flow_nominal=mWat_flow_nominal,
    dp_nominal=50,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Heater and cooler"
  Buildings.Fluid.FixedResistances.PressureDrop res_6(
    redeclare package Medium = Medium,
    dp_nominal=5,
    m_flow_nominal=0.5)
  Buildings.Fluid.FixedResistances.PressureDrop res_7(
    redeclare package Medium = Medium,
    dp_nominal=5,
    m_flow_nominal=0.5)
  Humidifier hea8(                               redeclare package Medium =
        Medium,
    m_flow_nominal=0.5,
    mWat_flow_nominal=mWat_flow_nominal,
    dp_nominal=50,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Heater and cooler"
  Buildings.Fluid.FixedResistances.PressureDrop res_8(
    redeclare package Medium = Medium,
    dp_nominal=5,
    m_flow_nominal=0.5)
  Buildings.Fluid.MixingVolumes.MixingVolume mix2(
                                           redeclare package Medium = Medium, V=
       0.000001,
    nPorts=2,
    m_flow_nominal=0.5,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
  Modelica.Blocks.Math.Add che5(k2=-1)
  Modelica.Blocks.Sources.RealExpression y9(y=hea6.T_b.T)
  Modelica.Blocks.Sources.RealExpression y10(
                                            y=hea5.T_b.T)
  Modelica.Blocks.Math.Add che6(k2=-1)
  Modelica.Blocks.Sources.RealExpression y11(
                                            y=hea6.T_a.T)
  Modelica.Blocks.Sources.RealExpression y12(
                                            y=hea5.T_a.T)
  Modelica.Blocks.Math.Add che7(k2=-1)
  Modelica.Blocks.Sources.RealExpression y13(
                                            y=hea8.T_b.T)
  Modelica.Blocks.Sources.RealExpression y14(
                                            y=hea7.T_b.T)
  Modelica.Blocks.Math.Add che8(k2=-1)
  Modelica.Blocks.Sources.RealExpression y15(
                                            y=hea8.T_a.T)
  Modelica.Blocks.Sources.RealExpression y16(
                                            y=hea7.T_a.T)
  Modelica.Blocks.Math.Add che9(k2=-1)
  Modelica.Blocks.Sources.RealExpression y17(y=hea2.T_b.T)
  Modelica.Blocks.Sources.RealExpression y18(y=hea5.T_b.T)
  Modelica.Blocks.Math.Add che10(k2=-1)
  Modelica.Blocks.Sources.RealExpression y19(y=hea4.T_a.T)
  Modelica.Blocks.Sources.RealExpression y20(y=hea7.T_a.T)
  Modelica.Blocks.Math.Add che11(k2=-1)
  Modelica.Blocks.Sources.RealExpression y21(y=hea2.X_b.X)
  Modelica.Blocks.Sources.RealExpression y22(y=hea1.X_b.X)
  Modelica.Blocks.Math.Add che12(k2=-1)
  Modelica.Blocks.Sources.RealExpression y23(y=hea2.X_a.X)
  Modelica.Blocks.Sources.RealExpression y24(y=hea1.X_a.X)
  Modelica.Blocks.Math.Add che13(k2=-1)
  Modelica.Blocks.Sources.RealExpression y25(
                                            y=hea4.X_b.X)
  Modelica.Blocks.Sources.RealExpression y26(
                                            y=hea3.X_b.X)
  Modelica.Blocks.Math.Add che14(k2=-1)
  Modelica.Blocks.Sources.RealExpression y27(
                                            y=hea4.X_a.X)
  Modelica.Blocks.Sources.RealExpression y28(
                                            y=hea3.X_a.X)
  Modelica.Blocks.Math.Add che15(k2=-1)
  Modelica.Blocks.Sources.RealExpression y29(
                                            y=hea6.X_b.X)
  Modelica.Blocks.Sources.RealExpression y30(
                                            y=hea5.X_b.X)
  Modelica.Blocks.Math.Add che16(k2=-1)
  Modelica.Blocks.Sources.RealExpression y31(
                                            y=hea6.X_a.X)
  Modelica.Blocks.Sources.RealExpression y32(
                                            y=hea5.X_a.X)
  Modelica.Blocks.Math.Add che17(k2=-1)
  Modelica.Blocks.Sources.RealExpression y33(
                                            y=hea8.X_b.X)
  Modelica.Blocks.Sources.RealExpression y34(
                                            y=hea7.X_b.X)
  Modelica.Blocks.Math.Add che18(k2=-1)
  Modelica.Blocks.Sources.RealExpression y35(
                                            y=hea8.X_a.X)
  Modelica.Blocks.Sources.RealExpression y36(
                                            y=hea7.X_a.X)
  Modelica.Blocks.Math.Add che19(k2=-1)
  Modelica.Blocks.Sources.RealExpression y37(y=hea2.X_b.X)
  Modelica.Blocks.Sources.RealExpression y38(y=hea5.X_b.X)
  Modelica.Blocks.Math.Add che20(k2=-1)
  Modelica.Blocks.Sources.RealExpression y39(y=hea4.X_a.X)
  Modelica.Blocks.Sources.RealExpression y40(y=hea7.X_a.X)

protected
  model Humidifier
    "Wrapper for the humidifier component with two-port sensors"
    extends Buildings.Fluid.Interfaces.PartialTwoPortInterface(
      redeclare replaceable package Medium = Medium);

    replaceable package Medium = Modelica.Media.Interfaces.PartialCondensingGases
      "Medium model";

    parameter Modelica.Units.SI.MassFlowRate m_flow_nominal
      "Nominal mass flow rate";
    parameter Modelica.Units.SI.PressureDifference dp_nominal
      "Nominal pressure difference";
    parameter Modelica.Units.SI.MassFlowRate mWat_flow_nominal
      "Nominal water mass flow rate";
    parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
      "Type of energy balance: dynamic (3 initialization options) or steady state"

    Buildings.Fluid.Humidifiers.Humidifier_u hum(
      redeclare final package Medium = Medium,
      final m_flow_nominal=m_flow_nominal,
      final mWat_flow_nominal=mWat_flow_nominal,
      final dp_nominal=dp_nominal,
      energyDynamics=energyDynamics) "Humidifier"
    Buildings.Fluid.Sensors.TemperatureTwoPort T_a(
      redeclare final package Medium = Medium,
      final m_flow_nominal=m_flow_nominal,
      tau=0) "Temperature at port_a"
    Buildings.Fluid.Sensors.TemperatureTwoPort T_b(
      redeclare final package Medium = Medium,
      final m_flow_nominal=m_flow_nominal,
      tau=0) "Temperature at port_a"
    Modelica.Blocks.Interfaces.RealInput u(unit="1") "Control input"
    Modelica.Blocks.Interfaces.RealOutput mWat_flow(unit="kg/s")
      "Water added to the fluid"
    Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort
      "Heat port for total heat exchange with the control volume"
    Buildings.Fluid.Sensors.MassFractionTwoPort X_a(
      redeclare final package Medium = Medium,
      final m_flow_nominal=m_flow_nominal,
      tau=0,
      final substanceName="water") "Mass fraction at port_a"
    Buildings.Fluid.Sensors.MassFractionTwoPort X_b(
      redeclare final package Medium = Medium,
      final m_flow_nominal=m_flow_nominal,
      tau=0,
      final substanceName="water") "Mass fraction at port_b"
  equation
    connect(T_a.port_b, hum.port_a)
    connect(T_b.port_a, hum.port_b)
    connect(hum.u, u)
    connect(hum.mWat_flow, mWat_flow)
    connect(heatPort, hum.heatPort)
    connect(T_a.port_a, X_a.port_b)
    connect(X_a.port_a, port_a)
    connect(T_b.port_b, X_b.port_a)
    connect(X_b.port_b, port_b)
  end Humidifier;
equation
  connect(POut.y,sin_1. p_in)
  connect(TDb.y,sou_1. T_in)
  connect(res_11.port_b, hea1.port_a)
  connect(u.y, hea1.u)
  connect(gain.y, hea2.u)
  connect(u.y, gain.u)
  connect(res_12.port_b, hea2.port_a)
  connect(res_2.port_b, hea3.port_a)
  connect(u.y, hea3.u)
  connect(gain.y, hea4.u)
  connect(res_3.port_b, hea4.port_a)
  connect(hea4.port_b, res_4.port_b)
  connect(hea1.port_b, hea2.port_b)
  connect(y1.y,che1. u1)
  connect(y2.y,che1. u2)
  connect(y3.y,che2. u1)
  connect(y4.y,che2. u2)
  connect(y5.y,che3. u1)
  connect(y6.y,che3. u2)
  connect(y7.y,che4. u1)
  connect(y8.y,che4. u2)
  connect(res_1.port_b, hea5.port_a)
  connect(res_5.port_b, hea6.port_a)
  connect(res_6.port_b,hea7. port_a)
  connect(res_7.port_b,hea8. port_a)
  connect(hea8.port_b,res_8. port_b)
  connect(hea5.port_b,hea6. port_b)
  connect(y9.y,che5. u1)
  connect(y10.y,che5. u2)
  connect(y11.y,che6. u1)
  connect(y12.y,che6. u2)
  connect(y13.y,che7. u1)
  connect(y14.y,che7. u2)
  connect(y15.y,che8. u1)
  connect(y16.y,che8. u2)
  connect(y17.y,che9. u1)
  connect(y18.y,che9. u2)
  connect(y19.y,che10. u1)
  connect(y20.y,che10. u2)
  connect(u.y, hea6.u)
  connect(u.y, hea8.u)
  connect(gain.y, hea5.u)
  connect(gain.y, hea7.u)
  connect(y21.y,che11. u1)
  connect(y22.y,che11. u2)
  connect(y23.y,che12. u1)
  connect(y24.y,che12. u2)
  connect(y25.y,che13. u1)
  connect(y26.y,che13. u2)
  connect(y27.y,che14. u1)
  connect(y28.y,che14. u2)
  connect(y29.y,che15. u1)
  connect(y30.y,che15. u2)
  connect(y31.y,che16. u1)
  connect(y32.y,che16. u2)
  connect(y33.y,che17. u1)
  connect(y34.y,che17. u2)
  connect(y35.y,che18. u1)
  connect(y36.y,che18. u2)
  connect(y37.y,che19. u1)
  connect(y38.y,che19. u2)
  connect(y39.y,che20. u1)
  connect(y40.y,che20. u2)
  connect(sin_1.ports[1], res_12.port_a)
  connect(sin_1.ports[2], res_3.port_a)
  connect(sou_1.ports[1], res_11.port_a)
  connect(sou_1.ports[2], res_2.port_a)
  connect(sin_1.ports[3], res_1.port_a)
  connect(sin_1.ports[4], res_6.port_a)
  connect(sou_1.ports[3], res_5.port_a)
  connect(sou_1.ports[4], res_7.port_a)
  connect(hea3.port_b, mix1.ports[1])
  connect(mix1.ports[2], res_4.port_a)
  connect(hea7.port_b, mix2.ports[1])
  connect(mix2.ports[2], res_8.port_a)
end Humidifier_u;


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


Test model for prescribed outlet state. Model that demonstrates

Buildings.Fluid.Interfaces.PrescribedOutlet
with mass fraction setpoint.

within Buildings.Fluid.Interfaces.Examples;
model PrescribedOutlet "Test model for prescribed outlet state"
  extends Modelica.Icons.Example;
  extends Buildings.Fluid.Interfaces.Examples.BaseClasses.PrescribedOutletState;

equation
  connect(setHeaHigPow.y[1], heaHigPow.TSet)
  connect(setHeaHigPow.y[2], heaHigPow.X_wSet)
  connect(setCooLimPow.y[1], cooLimPow.TSet)
  connect(setCooLimPow.y[2], cooLimPow.X_wSet)
  connect(setHeaCooUnl.y[1], heaCooUnl.TSet)
  connect(setHeaCooUnl.y[2], heaCooUnl.X_wSet)
  connect(setHeaCooUnl.y[1], steSta.TSet)
  connect(setHeaCooUnl.y[2], steSta.X_wSet)
end PrescribedOutlet;


Test model for prescribed outlet state. Model that demonstrates

Buildings.Fluid.Interfaces.PrescribedOutlet
with temperature setpoint.

within Buildings.Fluid.Interfaces.Examples;
model PrescribedOutlet_TSetOnly "Test model for prescribed outlet state"
  extends Modelica.Icons.Example;
  extends Buildings.Fluid.Interfaces.Examples.BaseClasses.PrescribedOutletState(
    steSta(use_X_wSet=false),
    heaHigPow(use_X_wSet=false),
    cooLimPow(use_X_wSet=false),
    heaCooUnl(use_X_wSet=false));

equation
  connect(setHeaHigPow.y[1], heaHigPow.TSet)
  connect(setCooLimPow.y[1], cooLimPow.TSet)
  connect(setHeaCooUnl.y[1], heaCooUnl.TSet)
  connect(setHeaCooUnl.y[1], steSta.TSet)
end PrescribedOutlet_TSetOnly;


Test model for prescribed outlet state

within Buildings.Fluid.Interfaces.Examples;
model PrescribedOutlet_Water
  "Test model for prescribed outlet state"
  extends Modelica.Icons.Example;
  extends Buildings.Fluid.Interfaces.Examples.BaseClasses.PrescribedOutletState(
    redeclare package Medium = Buildings.Media.Water,
    steSta(use_X_wSet=false),
    heaHigPow(use_X_wSet=false),
    cooLimPow(use_X_wSet=false),
    heaCooUnl(use_X_wSet=false));

equation
  connect(setHeaHigPow.y[1], heaHigPow.TSet)
  connect(setCooLimPow.y[1], cooLimPow.TSet)
  connect(setHeaCooUnl.y[1], heaCooUnl.TSet)
  connect(setHeaCooUnl.y[1], steSta.TSet)
end PrescribedOutlet_Water;


within Buildings.Fluid.Interfaces.Examples;
model PrescribedOutlet_X_wSetOnly
  "Test model for prescribed outlet state"
  extends Modelica.Icons.Example;
  extends Buildings.Fluid.Interfaces.Examples.BaseClasses.PrescribedOutletState(
    heaHigPow(use_TSet=false),
    cooLimPow(use_TSet=false),
    heaCooUnl(use_TSet=false),
    steSta(use_TSet=false));

equation
  connect(setHeaHigPow.y[2], heaHigPow.X_wSet)
  connect(setCooLimPow.y[2], cooLimPow.X_wSet)
  connect(setHeaCooUnl.y[2], heaCooUnl.X_wSet)
  connect(setHeaCooUnl.y[2], steSta.X_wSet)
end PrescribedOutlet_X_wSetOnly;


within Buildings.Fluid.Interfaces.Examples;
model ReverseFlowHumidifier
  "Model that tests the reverse flow for a humidifier"
  extends Modelica.Icons.Example;
package Medium = Buildings.Media.Air;
  Modelica.Blocks.Math.Add cheTem(k2=-1)
    "Check whether the outputs of the forward flow and reverse flow model are identical"
  Modelica.Blocks.Math.Add cheEnt(k2=-1)
    "Check whether the outputs of the forward flow and reverse flow model are identical"
  Modelica.Blocks.Math.Add cheMas(k2=-1)
    "Check whether the outputs of the forward flow and reverse flow model are identical"
  Buildings.Fluid.Humidifiers.Humidifier_u humBac(
    redeclare package Medium = Medium,
    dp_nominal=0,
    m_flow(start=1),
    m_flow_nominal=1,
    mWat_flow_nominal=0.1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Humidifier with backward flow"
  Buildings.Fluid.Humidifiers.Humidifier_u humFor(
    redeclare package Medium = Medium,
    dp_nominal=0,
    m_flow(start=1),
    m_flow_nominal=1,
    mWat_flow_nominal=0.1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Humidifier with forward flow"
  Modelica.Blocks.Sources.Constant u2(k=0.01) "Control input"
  Modelica.Fluid.Sources.MassFlowSource_T source1(
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    use_T_in=false,
    use_X_in=false,
    T(displayUnit="K") = 323.15,
    X={0.01,0.99},
    nPorts=1,
    m_flow=0.5) "Fluid source"
  Buildings.Fluid.Sources.Boundary_pT  sink1(
    redeclare package Medium = Medium,
    nPorts=2) "Fluid sink"
  Sensors.SpecificEnthalpy senEnt1(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
    "Specific enthalpy sensor"
  Buildings.Fluid.Sensors.Temperature senTem1(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
    "Temperature sensor"
  Sensors.MassFraction senMas1(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
    "Mass fraction sensor"
  Buildings.Fluid.Sensors.Temperature senTem2(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
    "Temperature sensor"
  Sensors.SpecificEnthalpy senEnt2(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
    "Specific enthalpy sensor"
  Sensors.MassFraction senMas2(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
    "Mass fraction sensor"
  FixedResistances.PressureDrop res1(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    from_dp=true,
    linearized=false,
    dp_nominal=1000) "Fixed resistance"
  FixedResistances.PressureDrop res2(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    from_dp=true,
    linearized=false,
    dp_nominal=1000) "Fixed resistance"
  Modelica.Fluid.Sources.MassFlowSource_T source2(
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    use_T_in=false,
    use_X_in=false,
    T(displayUnit="K") = 323.15,
    X={0.01,0.99},
    nPorts=1,
    m_flow=0.5) "Fluid source"

equation
  connect(u2.y, humFor.u)
  connect(u2.y, humBac.u)
  connect(humFor.port_b, senTem1.port)
  connect(humFor.port_b, senEnt1.port)
  connect(humFor.port_b, senMas1.port)
  connect(humBac.port_a, senTem2.port)
  connect(humBac.port_a, senEnt2.port)
  connect(humBac.port_a, senMas2.port)
  connect(humFor.port_b, res1.port_a)
  connect(res1.port_b, sink1.ports[1])
  connect(humBac.port_a, res2.port_a)
  connect(res2.port_b, sink1.ports[2])
  connect(senTem1.T,cheTem. u1)
  connect(senEnt1.h_out,cheEnt. u1)
  connect(senMas1.X,cheMas. u1)
  connect(senTem2.T,cheTem. u2)
  connect(senEnt2.h_out,cheEnt. u2)
  connect(senMas2.X,cheMas. u2)
  connect(humFor.port_a, source1.ports[1])
  connect(source2.ports[1], humBac.port_b)
end ReverseFlowHumidifier;


within Buildings.Fluid.Interfaces.Examples;
model ReverseFlowMassExchanger
  "Model that tests the reverse flow for a mass exchanger"
  extends Modelica.Icons.Example;
package Medium = Buildings.Media.Air;
  Modelica.Blocks.Math.Add cheTem(k2=-1)
    "Check whether the outputs of the forward flow and reverse flow model are identical"
  Modelica.Blocks.Math.Add cheEnt(k2=-1)
    "Check whether the outputs of the forward flow and reverse flow model are identical"
  Modelica.Blocks.Math.Add cheMas(k2=-1)
    "Check whether the outputs of the forward flow and reverse flow model are identical"
  Modelica.Fluid.Sources.MassFlowSource_T source2(
    m_flow=1,
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    use_T_in=false,
    use_X_in=false,
    nPorts=1,
    T(displayUnit="degC") = 303.15,
    X={0.02,0.98})
  Buildings.Fluid.MassExchangers.ConstantEffectiveness masExcFor(
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    m1_flow_nominal=1,
    m2_flow_nominal=1,
    dp1_nominal=0,
    dp2_nominal=0,
    epsL=0) "Mass exchanger with forward flow"
  Buildings.Fluid.MassExchangers.ConstantEffectiveness masExcRev(
    redeclare package Medium1 = Medium,
    redeclare package Medium2 = Medium,
    m1_flow_nominal=1,
    m2_flow_nominal=1,
    dp1_nominal=0,
    dp2_nominal=0,
    epsL=0) "Mass exchanger with reverse flow"
  Buildings.Fluid.Sources.Boundary_pT sink2(
     redeclare package Medium = Medium,
     nPorts=2) "Fluid sink"
  FixedResistances.PressureDrop res3(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    from_dp=true,
    linearized=false,
    dp_nominal=1000) "Fixed resistance"
  FixedResistances.PressureDrop res4(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    from_dp=true,
    linearized=false,
    dp_nominal=1000) "Fixed resistance"
  Sensors.SpecificEnthalpy senEnt3(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
  Buildings.Fluid.Sensors.Temperature senTem3(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
  Sensors.MassFraction senMas3(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
  Sensors.SpecificEnthalpy senEnt4(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
  Buildings.Fluid.Sensors.Temperature senTem4(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
  Sensors.MassFraction senMas4(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
  Modelica.Blocks.Math.Add cheTem1(k2=-1)
    "Check whether the outputs of the forward flow and reverse flow model are identical"
  Modelica.Blocks.Math.Add cheEnt1(k2=-1)
    "Check whether the outputs of the forward flow and reverse flow model are identical"
  Modelica.Blocks.Math.Add cheMas1(k2=-1)
    "Check whether the outputs of the forward flow and reverse flow model are identical"
  Modelica.Fluid.Sources.MassFlowSource_T source3(
    m_flow=1,
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    use_T_in=false,
    use_X_in=false,
    X={0.01,0.99},
    nPorts=1,
    T(displayUnit="degC") = 293.15)
  Modelica.Fluid.Sources.MassFlowSource_T source4(
    m_flow=1,
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    use_T_in=false,
    use_X_in=false,
    nPorts=1,
    T(displayUnit="degC") = 303.15,
    X={0.02,0.98})

  Modelica.Fluid.Sources.MassFlowSource_T source1(
    m_flow=1,
    redeclare package Medium = Medium,
    use_m_flow_in=false,
    use_T_in=false,
    use_X_in=false,
    X={0.01,0.99},
    nPorts=1,
    T(displayUnit="degC") = 293.15)
  Sources.Boundary_pT sink1(
    redeclare package Medium = Medium,
    nPorts=2) "Fluid sink"
  Sensors.SpecificEnthalpy senEnt1(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
  Buildings.Fluid.Sensors.Temperature senTem1(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
  Sensors.MassFraction senMas1(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
  Buildings.Fluid.Sensors.Temperature senTem2(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
  Sensors.SpecificEnthalpy senEnt2(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
  Sensors.MassFraction senMas2(redeclare package Medium = Medium,
      warnAboutOnePortConnection=false)
  FixedResistances.PressureDrop res1(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    from_dp=true,
    linearized=false,
    dp_nominal=1000) "Fixed resistance"
  FixedResistances.PressureDrop res2(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    from_dp=true,
    linearized=false,
    dp_nominal=1000) "Fixed resistance"

equation
  connect(res1.port_b, sink1.ports[1])
  connect(res2.port_b, sink1.ports[2])
  connect(senTem1.T,cheTem. u1)
  connect(senEnt1.h_out,cheEnt. u1)
  connect(senMas1.X,cheMas. u1)
  connect(senTem2.T,cheTem. u2)
  connect(senEnt2.h_out,cheEnt. u2)
  connect(senMas2.X,cheMas. u2)
  connect(masExcFor.port_b1, res1.port_a)
  connect(masExcFor.port_a1, source1.ports[1])
  connect(masExcRev.port_a1, res2.port_a)
  connect(source2.ports[1], masExcFor.port_a2)
  connect(masExcRev.port_a1, senTem2.port)
  connect(masExcRev.port_a1, senEnt2.port)
  connect(masExcRev.port_a1, senMas2.port)
  connect(masExcFor.port_b1, senTem1.port)
  connect(masExcFor.port_b1, senEnt1.port)
  connect(masExcFor.port_b1, senMas1.port)
  connect(masExcFor.port_b2, res3.port_a)
  connect(masExcRev.port_a2, res4.port_a)
  connect(res3.port_b, sink2.ports[1])
  connect(res4.port_b, sink2.ports[2])
  connect(senTem3.T,cheTem1. u1)
  connect(senTem4.T,cheTem1. u2)
  connect(senEnt3.h_out,cheEnt1. u1)
  connect(senEnt4.h_out,cheEnt1. u2)
  connect(senMas3.X,cheMas1. u1)
  connect(senMas4.X,cheMas1. u2)
  connect(masExcFor.port_b2, senTem3.port)
  connect(masExcFor.port_b2, senEnt3.port)
  connect(masExcFor.port_b2, senMas3.port)
  connect(masExcRev.port_a2, senTem4.port)
  connect(masExcRev.port_a2, senEnt4.port)
  connect(masExcRev.port_a2, senMas4.port)
  connect(source3.ports[1], masExcRev.port_b1)
  connect(source4.ports[1], masExcRev.port_b2)
end ReverseFlowMassExchanger;


within Buildings.Fluid.Interfaces.Examples;
model StaticTwoPortConservationEquation
  "Model that tests the static two port conservation equation"
extends Modelica.Icons.Example;
 package MediumW = Buildings.Media.Water "Medium model";
 package MediumA = Buildings.Media.Air "Medium model";

  Modelica.Blocks.Sources.Constant mWat_flow(k=0)
    "Water mass flow rate added to the control volume"
  Modelica.Blocks.Sources.TimeTable QSen_flow(startTime=0, table=[
                                0,-100;
                                900,-100;
                                900,0;
                                1800,0;
                                1800,100])
    "Sensible heat flow rate added to the control volume"

  SubModel modWatRev(
    redeclare package Medium = MediumW,
    allowFlowReversal=true,
    use_mWat_flow = false) "Submodel for energy and mass balance"
  SubModel modWatNoRev(
    redeclare package Medium = MediumW,
    allowFlowReversal=false,
    use_mWat_flow = false) "Submodel for energy and mass balance"
  SubModel modAirRev(
    redeclare package Medium = MediumA,
    allowFlowReversal=true,
    use_mWat_flow = true) "Submodel for energy and mass balance"
  SubModel modAirNoRev(
    redeclare package Medium = MediumA,
    allowFlowReversal=false,
    use_mWat_flow = true) "Submodel for energy and mass balance"
equation

  connect(QSen_flow.y, modWatRev.Q_flow)
  connect(mWat_flow.y, modWatRev.mWat_flow)
protected
  model SubModel
    replaceable package Medium = Modelica.Media.Interfaces.PartialMedium
      "Medium model";
    Sources.MassFlowSource_T bou(
      nPorts=1,
      redeclare package Medium = Medium,
      m_flow=0.01) "Boundary condition for mass flow rate"
    Buildings.Fluid.Interfaces.StaticTwoPortConservationEquation conEqn(
      redeclare package Medium = Medium,
      m_flow_nominal=0.01,
      show_T=true,
      allowFlowReversal=allowFlowReversal,
      use_mWat_flow=use_mWat_flow,
      prescribedHeatFlowRate=true) "Steady-state conservation equation"
    Buildings.Fluid.Sources.Boundary_pT sin(
      use_p_in=false,
      redeclare package Medium = Medium,
      nPorts=1,
      p=101325,
      T=283.15) "Sink"

    Modelica.Blocks.Interfaces.RealInput Q_flow(unit="W")
    Modelica.Blocks.Interfaces.RealInput mWat_flow(unit="kg/s")
    parameter Boolean use_mWat_flow
      "Set to true to enable exchange of moisture";
    parameter Boolean allowFlowReversal=true
      "= false to simplify equations, assuming, but not enforcing, no flow reversal";
  equation
    connect(conEqn.port_b, sin.ports[1])
    connect(conEqn.port_a, bou.ports[1])
    connect(Q_flow, conEqn.Q_flow)
    connect(mWat_flow, conEqn.mWat_flow)
  end SubModel;
equation
  connect(QSen_flow.y, modWatNoRev.Q_flow)
  connect(mWat_flow.y, modWatNoRev.mWat_flow)
  connect(QSen_flow.y, modAirRev.Q_flow)
  connect(mWat_flow.y, modAirRev.mWat_flow)
  connect(QSen_flow.y, modAirNoRev.Q_flow)
  connect(mWat_flow.y, modAirNoRev.mWat_flow)
end StaticTwoPortConservationEquation;


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


Test model for prescribed outlet state

within Buildings.Fluid.Interfaces.Examples.BaseClasses;
partial model PrescribedOutletState "Test model for prescribed outlet state"

  replaceable package Medium = Buildings.Media.Air
     constrainedby Modelica.Media.Interfaces.PartialMedium  "Medium model";

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=0.1
    "Nominal mass flow rate";

  Buildings.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    use_T_in=false,
    p(displayUnit="Pa"),
    T=293.15,
    nPorts=4) "Sink"
  Buildings.Fluid.Interfaces.PrescribedOutlet heaHigPow(
    redeclare package Medium = Medium,
    QMax_flow=1.0e10,
    mWatMax_flow = 0.001,
    m_flow_small=1E-4*abs(m_flow_nominal),
    show_T=true,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Steady-state model of the heater with high capacity"
  Modelica.Blocks.Sources.CombiTimeTable setHeaHigPow(table=[
    0,    20.0, 0.012;
    120,  20.0, 0.012;
    500,  60.0, 0.020;
    800,  10.0, 0.005;
    1200, 30.0, 0.015],
    offset={273.15,0},
    smoothness = Modelica.Blocks.Types.Smoothness.ConstantSegments)
    "Setpoint heating and humidification"
  Buildings.Fluid.Interfaces.PrescribedOutlet cooLimPow(
    redeclare package Medium = Medium,
    QMin_flow=-1000,
    mWatMin_flow = -0.001,
    m_flow_small=1E-4*abs(m_flow_nominal),
    show_T=true,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Steady-state model of the cooler with limited capacity"
  Modelica.Blocks.Sources.CombiTimeTable setCooLimPow(table=[
    0,    20.0, 0.008;
    120,  20.0, 0.008;
    500,  15.0, 0.004;
    800,  60.0, 0.015;
    1200, 10.0, 0.002],
    offset={273.15,0},
    smoothness = Modelica.Blocks.Types.Smoothness.ConstantSegments)
    "Setpoint cooling and dehumidification"
  Buildings.Fluid.Interfaces.PrescribedOutlet heaCooUnl(
    redeclare package Medium = Medium,
    m_flow_small=1E-4*abs(m_flow_nominal),
    show_T=true,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Steady-state model of the heater or cooler with unlimited capacity"
  Buildings.Fluid.Interfaces.PrescribedOutlet steSta(
    redeclare package Medium = Medium,
    m_flow_small=1E-4*abs(m_flow_nominal),
    show_T=true,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Steady-state model of the heater or cooler with unlimited capacity"
  Modelica.Blocks.Sources.CombiTimeTable setHeaCooUnl(table=[
    0,    20.0, 0.012;
    120,  20.0, 0.012;
    500,  15.0, 0.008;
    800,  10.0, 0.005;
    1200, 30.0, 0.015],
    offset={273.15,0},
    smoothness = Modelica.Blocks.Types.Smoothness.ConstantSegments)
    "Setpoint cooling, heating, dehumidification and humidification"
  Modelica.Blocks.Sources.Ramp m_flow(
    height=-2*m_flow_nominal,
    duration=100,
    offset=m_flow_nominal,
    startTime=1000) "Mass flow rate"
  Buildings.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    T=293.15,
    nPorts=1) "Flow source"
  Buildings.Fluid.Sources.MassFlowSource_T sou2(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    T=293.15,
    nPorts=1) "Flow source"
  Buildings.Fluid.Sources.MassFlowSource_T sou3(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    T=293.15,
    nPorts=1) "Flow source"
  Buildings.Fluid.Sources.MassFlowSource_T sou4(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    T=293.15,
    nPorts=1) "Flow source"
  Buildings.Fluid.Sensors.TemperatureTwoPort THeaHigPowIn(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final tau=0) "Temperature sensor at the inlet of heaHigPow"
  Buildings.Fluid.Sensors.TemperatureTwoPort THeaHigPowOut(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final tau=0) "Temperature sensor at the outlet of heaHigPow"
  Buildings.Fluid.Sensors.TemperatureTwoPort TCooLimPowIn(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final tau=0) "Temperature sensor at the inlet of cooLimPow"
  Buildings.Fluid.Sensors.TemperatureTwoPort TCooLimPowOut(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final tau=0) "Temperature sensor at the outlet of cooLimPow"
  Buildings.Fluid.Sensors.TemperatureTwoPort THeaCooUnlIn(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final tau=0) "Temperature sensor at the inlet of heaCooUnl"
  Buildings.Fluid.Sensors.TemperatureTwoPort THeaCooUnlOut(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final tau=0) "Temperature sensor at the outlet of heaCooUnl"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSteStaIn(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final tau=0) "Temperature sensor at the inlet of steSta"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSteStaOut(
    redeclare final package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final tau=0) "Temperature sensor at the outlet of steSta"
equation

  connect(m_flow.y, sou1.m_flow_in)
  connect(m_flow.y, sou2.m_flow_in)
  connect(m_flow.y, sou3.m_flow_in)
  connect(m_flow.y, sou4.m_flow_in)
  connect(sou1.ports[1], THeaHigPowIn.port_a)
  connect(THeaHigPowIn.port_b, heaHigPow.port_a)
  connect(heaHigPow.port_b, THeaHigPowOut.port_a)
  connect(THeaHigPowOut.port_b, sin.ports[1])
  connect(sou2.ports[1], TCooLimPowIn.port_a)
  connect(TCooLimPowIn.port_b, cooLimPow.port_a)
  connect(cooLimPow.port_b, TCooLimPowOut.port_a)
  connect(TCooLimPowOut.port_b, sin.ports[2])
  connect(sou3.ports[1], THeaCooUnlIn.port_a)
  connect(THeaCooUnlIn.port_b, heaCooUnl.port_a)
  connect(heaCooUnl.port_b, THeaCooUnlOut.port_a)
  connect(THeaCooUnlOut.port_b, sin.ports[3])
  connect(sou4.ports[1], TSteStaIn.port_a)
  connect(TSteStaIn.port_b, steSta.port_a)
  connect(steSta.port_b, TSteStaOut.port_a)
  connect(TSteStaOut.port_b, sin.ports[4])
end PrescribedOutletState;


within Buildings.Fluid.MassExchangers;
model ConstantEffectiveness
  "Heat and moisture exchanger with constant effectiveness"
  extends Buildings.Fluid.HeatExchangers.BaseClasses.PartialEffectiveness(
  redeclare replaceable package Medium1 =
        Modelica.Media.Interfaces.PartialCondensingGases,
  redeclare replaceable package Medium2 =
        Modelica.Media.Interfaces.PartialCondensingGases,
  sensibleOnly1=false,
  sensibleOnly2=false,
  final prescribedHeatFlowRate1=true,
  final prescribedHeatFlowRate2=true,
  Q1_flow = epsS * QMax_flow + QLat_flow,
  Q2_flow = -Q1_flow,
  mWat1_flow = +mWat_flow,
  mWat2_flow = -mWat_flow);

  parameter Modelica.Units.SI.Efficiency epsS(max=1) = 0.8
    "Sensible heat exchanger effectiveness";
  parameter Modelica.Units.SI.Efficiency epsL(max=1) = 0.8
    "Latent heat exchanger effectiveness";

  Modelica.Units.SI.HeatFlowRate QLat_flow
    "Latent heat exchange from medium 2 to medium 1";

  Medium1.MassFraction X_w_in1 "Inlet water mass fraction of medium 1";
  Medium2.MassFraction X_w_in2 "Inlet water mass fraction of medium 2";

  Modelica.Units.SI.MassFlowRate mWat_flow
    "Water flow rate from medium 2 to medium 1";
  Modelica.Units.SI.MassFlowRate mMax_flow
    "Maximum water flow rate from medium 2 to medium 1";

protected
  parameter Integer i1_w(min=1, fixed=false) "Index for water substance";
  parameter Integer i2_w(min=1, fixed=false) "Index for water substance";
  Real gai1(min=0, max=1) "Auxiliary variable for smoothing at zero flow";
  Real gai2(min=0, max=1) "Auxiliary variable for smoothing at zero flow";
initial algorithm
  i1_w:= -1;
  i2_w:= -1;
  for i in 1:Medium1.nXi loop
      if Modelica.Utilities.Strings.isEqual(string1=Medium1.substanceNames[i],
                                            string2="Water",
                                            caseSensitive=false) then
      i1_w := i;
    end if;
   end for;
  for i in 1:Medium2.nXi loop
      if Modelica.Utilities.Strings.isEqual(string1=Medium2.substanceNames[i],
                                            string2="Water",
                                            caseSensitive=false) then
      i2_w := i;
    end if;
   end for;
    assert(i1_w > 0, "Substance 'water' is not present in Medium1 '"
         + Medium1.mediumName + "'.\n"
         + "Check medium model.");
    assert(i2_w > 0, "Substance 'water' is not present in Medium2 '"
         + Medium2.mediumName + "'.\n"
         + "Check medium model.");
equation
  // Definitions for effectiveness model
  X_w_in1 = Modelica.Fluid.Utilities.regStep(m1_flow,
                  state_a1_inflow.X[i1_w],
                  state_b1_inflow.X[i1_w], m1_flow_small);
  X_w_in2 = Modelica.Fluid.Utilities.regStep(m2_flow,
                  state_a2_inflow.X[i2_w],
                  state_b2_inflow.X[i2_w], m2_flow_small);

  // mass exchange
  // Compute a gain that goes to zero near zero flow rate.
  // This is required to smoothen the heat transfer at very small flow rates.
  // Note that gaiK = 1 for abs(mK_flow) > mK_flow_small
  gai1 = Modelica.Fluid.Utilities.regStep(abs(m1_flow) - 0.75*m1_flow_small,
              1, 0, 0.25*m1_flow_small);
  gai2 = Modelica.Fluid.Utilities.regStep(abs(m2_flow) - 0.75*m2_flow_small,
              1, 0, 0.25*m2_flow_small);

  mMax_flow = smooth(1, min(smooth(1, gai1 * abs(m1_flow)),
                            smooth(1, gai2 * abs(m2_flow)))) * (X_w_in2 - X_w_in1);
  mWat_flow = epsL * mMax_flow;
  // As enthalpyOfCondensingGas is dominated by the latent heat of phase change,
  // we simplify and use Medium1.enthalpyOfVaporization for the
  // latent heat that is exchanged among the fluid streams.
  // This is simply added to QSen_flow, while mass is conserved because
  // of the assignment of mWat1_flow and mWat2_flow.
  QLat_flow = mWat_flow * Medium1.enthalpyOfVaporization(Medium1.T_default);
end ConstantEffectiveness;


Package with mass exchanger models

within Buildings.Fluid;
package MassExchangers "Package with mass exchanger models"
  extends Modelica.Icons.VariantsPackage;
end MassExchangers;


Water temperature

within Buildings.Fluid.MassExchangers.Examples;
model ConstantEffectiveness
  extends Modelica.Icons.Example;

 package Medium1 = Buildings.Media.Air;
 package Medium2 = Buildings.Media.Air;

  Buildings.Fluid.Sources.Boundary_pT sin_2(
    redeclare package Medium = Medium2, T=273.15 + 10,
    use_p_in=true,
    nPorts=1)
    Modelica.Blocks.Sources.Ramp PIn(
    height=200,
    duration=60,
    offset=101330)
  Buildings.Fluid.Sources.Boundary_pT sou_2(
    redeclare package Medium = Medium2, T=273.15 + 5,
    use_p_in=true,
    use_T_in=true,
    nPorts=1)
    Modelica.Blocks.Sources.Ramp TWat(
    height=10,
    duration=60,
    offset=273.15 + 30,
    startTime=60) "Water temperature"
  Modelica.Blocks.Sources.Constant TDb(k=293.15) "Drybulb temperature"
    Modelica.Blocks.Sources.Constant POut(k=101325)
  Buildings.Fluid.Sources.Boundary_pT sin_1(
    redeclare package Medium = Medium1,
    T=273.15 + 30,
    X={0.012,1 - 0.012},
    use_p_in=true,
    p=300000,
    nPorts=1)
  Buildings.Fluid.Sources.Boundary_pT sou_1(
    redeclare package Medium = Medium1,
    T=273.15 + 50,
    X={0.012,1 - 0.012},
    use_T_in=true,
    p=100000,
    nPorts=1)
    Modelica.Blocks.Sources.Ramp PSin_1(
    duration=60,
    startTime=240,
    height=100,
    offset=1E5 - 110)
  Buildings.Fluid.MassExchangers.ConstantEffectiveness hex(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    m1_flow(start=5),
    m2_flow(start=5),
    m1_flow_nominal=5,
    m2_flow_nominal=5,
    dp1_nominal=100,
    dp2_nominal=100,
    show_T=true)

equation
  connect(PIn.y,sou_2. p_in)
  connect(TDb.y, sou_2.T_in)
  connect(TWat.y, sou_1.T_in)
  connect(PSin_1.y, sin_1.p_in)
  connect(sou_1.ports[1], hex.port_a1)
  connect(hex.port_a2, sou_2.ports[1])
  connect(POut.y, sin_2.p_in)
  connect(hex.port_b1, sin_1.ports[1])
  connect(hex.port_b2, sin_2.ports[1])
end ConstantEffectiveness;


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


Zero flow test for constants effectiveness mass exchanger. This model tests whether
ConstantEffectiveness
works correctly at zero flow if one stream is zero.

within Buildings.Fluid.MassExchangers.Validation;
model ConstantEffectivenessZeroFlow
  "Zero flow test for constants effectiveness mass exchanger"
  extends Buildings.Fluid.MassExchangers.Examples.ConstantEffectiveness(
    PSin_1(
      height=0,
      offset=1E5), PIn(height=0, offset=101325));
end ConstantEffectivenessZeroFlow;


Zero flow test for constants effectiveness mass exchanger. This model tests whether
Buildings.Fluid.MassExchangers.ConstantEffectiveness
works correctly at zero flow if both streams are zero.

within Buildings.Fluid.MassExchangers.Validation;
model ConstantEffectivenessZeroFlowBothStreams
  "Zero flow test for constants effectiveness mass exchanger"
  extends Buildings.Fluid.MassExchangers.Examples.ConstantEffectiveness(
    PSin_1(
      height=0,
      offset=1E5),
    PIn(
      height=0,
      offset=101325));
end ConstantEffectivenessZeroFlowBothStreams;


Validation examples

within Buildings.Fluid.MassExchangers;
package Validation "Validation examples"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Mixing volume with inlet and outlet ports (flow reversal is allowed). This model represents an instantaneously mixed volume.
Potential and kinetic energy at the port are neglected,
and there is no pressure drop at the ports.
The volume can exchange heat through its heatPort.

within Buildings.Fluid.MixingVolumes;
model MixingVolume
  "Mixing volume with inlet and outlet ports (flow reversal is allowed)"
  extends Buildings.Fluid.MixingVolumes.BaseClasses.PartialMixingVolume(
    final initialize_p = not Medium.singleState,
    steBal(final use_C_flow = use_C_flow),
    dynBal(final use_C_flow = use_C_flow));

  parameter Boolean use_C_flow = false
    "Set to true to enable input connector for trace substance"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort(
    T(start=T_start)) "Heat port for heat exchange with the control volume"

  Modelica.Blocks.Interfaces.RealInput[Medium.nC] C_flow if use_C_flow
    "Trace substance mass flow rate added to the medium"

equation
  connect(heaFloSen.port_a, heatPort)
  connect(C_flow, steBal.C_flow)
  connect(C_flow, dynBal.C_flow)
end MixingVolume;


Mixing volume with heat port for latent heat exchange, to be used if moisture is added or removed. Model for an ideally mixed fluid volume and the ability
to store mass and energy. The volume is fixed,
and latent and sensible heat can be exchanged.

within Buildings.Fluid.MixingVolumes;
model MixingVolumeMoistAir
  "Mixing volume with heat port for latent heat exchange, to be used if moisture is added or removed"
  extends Buildings.Fluid.MixingVolumes.BaseClasses.PartialMixingVolume(
    dynBal(
      final use_mWat_flow = true,
      final use_C_flow = use_C_flow),
    steBal(final use_mWat_flow = true,
      final use_C_flow = use_C_flow),
    final initialize_p = not Medium.singleState);

  parameter Boolean use_C_flow = false
    "Set to true to enable input connector for trace substance"

  Modelica.Blocks.Interfaces.RealInput mWat_flow(final quantity="MassFlowRate",
                                                 final unit = "kg/s")
    "Water flow rate added into the medium"
  Modelica.Blocks.Interfaces.RealOutput X_w(final unit="kg/kg")
    "Species composition of medium"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort(
    T(start=T_start))
    "Heat port for sensible plus latent heat exchange with the control volume"

  Modelica.Blocks.Interfaces.RealInput[Medium.nC] C_flow if use_C_flow
    "Trace substance mass flow rate added to the medium"

protected
  parameter Real s[Medium.nXi] = {
  if Modelica.Utilities.Strings.isEqual(string1=Medium.substanceNames[i],
                                            string2="Water",
                                            caseSensitive=false) then 1 else 0
                                            for i in 1:Medium.nXi}
    "Vector with zero everywhere except where species is";

  Modelica.Blocks.Sources.RealExpression XLiq(y=s*Xi)
    "Species composition of the medium"
equation
  connect(mWat_flow, steBal.mWat_flow)
  connect(mWat_flow, dynBal.mWat_flow)
  connect(XLiq.y, X_w)
  connect(heaFloSen.port_a, heatPort)
  connect(C_flow, steBal.C_flow)
  connect(C_flow, dynBal.C_flow)
end MixingVolumeMoistAir;


Package with mixing volumes

within Buildings.Fluid;
package MixingVolumes "Package with mixing volumes"
  extends Modelica.Icons.VariantsPackage;
end MixingVolumes;


Mixing volume with heat and moisture port and initialize_p not set to final. Mixing volume with a heat port.

within Buildings.Fluid.MixingVolumes.BaseClasses;
model MixingVolumeHeatMoisturePort
  "Mixing volume with heat and moisture port and initialize_p not set to final"
  extends Buildings.Fluid.MixingVolumes.BaseClasses.PartialMixingVolume(
  dynBal(
      final use_mWat_flow = true),
    steBal(
      final use_mWat_flow = true));

   Modelica.Blocks.Interfaces.RealInput mWat_flow(final quantity="MassFlowRate",
                                                 final unit = "kg/s")
    "Water flow rate added into the medium"
  Modelica.Blocks.Interfaces.RealOutput X_w(final unit="kg/kg")
    "Species composition of medium"

    Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort(
      T(start=T_start)) "Heat port for heat exchange with the control volume"
protected
  parameter Real s[Medium.nXi] = {
  if Modelica.Utilities.Strings.isEqual(string1=Medium.substanceNames[i],
                                            string2="Water",
                                            caseSensitive=false) then 1 else 0
                                            for i in 1:Medium.nXi}
    "Vector with zero everywhere except where species is";

  Modelica.Blocks.Sources.RealExpression XLiq(y=s*Xi)
    "Species composition of the medium"

equation
  connect(mWat_flow, steBal.mWat_flow)
  connect(mWat_flow, dynBal.mWat_flow)
  connect(XLiq.y, X_w)
  connect(heaFloSen.port_a, heatPort)
end MixingVolumeHeatMoisturePort;


Mixing volume with heat port and initialize_p not set to final. Mixing volume with a heat port.

within Buildings.Fluid.MixingVolumes.BaseClasses;
model MixingVolumeHeatPort
  "Mixing volume with heat port and initialize_p not set to final"
  extends Buildings.Fluid.MixingVolumes.BaseClasses.PartialMixingVolume;
    Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort(
      T(start=T_start)) "Heat port for heat exchange with the control volume"
equation
    connect(heaFloSen.port_a, heatPort)
end MixingVolumeHeatPort;


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


within Buildings.Fluid.MixingVolumes.BaseClasses;
model PartialMixingVolume
  "Partial mixing volume with inlet and outlet ports (flow reversal is allowed)"

  extends Buildings.Fluid.Interfaces.LumpedVolumeDeclarations;
  parameter Boolean initialize_p = not Medium.singleState
    "= true to set up initial equations for pressure"

  // We set prescribedHeatFlowRate=false so that the
  // volume works without the user having to set this advanced parameter,
  // but to get high robustness, a user can set it to the appropriate value
  // as described in the info section.
  constant Boolean prescribedHeatFlowRate = false
    "Set to true if the model has a prescribed heat flow at its heatPort. If the heat flow rate at the heatPort is only based on temperature difference, then set to false";

  constant Boolean simplify_mWat_flow = true
    "Set to true to cause port_a.m_flow + port_b.m_flow = 0 even if mWat_flow is non-zero";

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal(min=0)
    "Nominal mass flow rate"
  // Port definitions
  parameter Integer nPorts=0 "Number of ports"
  parameter Modelica.Units.SI.MassFlowRate m_flow_small(min=0) = 1E-4*abs(
    m_flow_nominal) "Small mass flow rate for regularization of zero flow"
  parameter Boolean allowFlowReversal = true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal. Used only if model has two ports."
  parameter Modelica.Units.SI.Volume V "Volume";
  Modelica.Fluid.Vessels.BaseClasses.VesselFluidPorts_b ports[nPorts](
      redeclare each package Medium = Medium,
      each h_outflow(nominal=Medium.h_default),
      each Xi_outflow(each nominal=0.01)
      ) "Fluid inlets and outlets"

  Medium.Temperature T = Medium.temperature_phX(
    p=p,
    h=hOut_internal,
    X=if Medium.reducedX then cat(1, Xi, {1-sum(Xi)}) else Xi)
    "Temperature of the fluid";
  Modelica.Blocks.Interfaces.RealOutput U(unit="J")
    "Internal energy of the component";
  Modelica.Units.SI.Pressure p=if nPorts > 0 then ports[1].p else p_start
    "Pressure of the fluid";
  Modelica.Blocks.Interfaces.RealOutput m(unit="kg") "Mass of the component";
  Modelica.Units.SI.MassFraction Xi[Medium.nXi]=XiOut_internal
    "Species concentration of the fluid";
  Modelica.Blocks.Interfaces.RealOutput mXi[Medium.nXi](each unit="kg")
    "Species mass of the component";
  Medium.ExtraProperty C[Medium.nC](nominal=C_nominal) = COut_internal
    "Trace substance mixture content";
  Modelica.Blocks.Interfaces.RealOutput mC[Medium.nC](each unit="kg")
    "Trace substance mass of the component";

protected
  Buildings.Fluid.Interfaces.StaticTwoPortConservationEquation steBal(
    final simplify_mWat_flow = simplify_mWat_flow,
    redeclare final package Medium=Medium,
    final m_flow_nominal = m_flow_nominal,
    final allowFlowReversal = allowFlowReversal,
    final m_flow_small = m_flow_small,
    final prescribedHeatFlowRate=prescribedHeatFlowRate,
    hOut(start=Medium.specificEnthalpy_pTX(
                 p=p_start,
                 T=T_start,
                 X=X_start)))
      if useSteadyStateTwoPort "Model for steady-state balance if nPorts=2"
  Buildings.Fluid.Interfaces.ConservationEquation dynBal(
    final simplify_mWat_flow = simplify_mWat_flow,
    redeclare final package Medium = Medium,
    final energyDynamics=energyDynamics,
    final massDynamics=massDynamics,
    final p_start=p_start,
    final T_start=T_start,
    final X_start=X_start,
    final C_start=C_start,
    final C_nominal=C_nominal,
    final fluidVolume = V,
    final initialize_p = initialize_p,
    m(start=V*rho_start),
    nPorts=nPorts,
    final mSenFac=mSenFac)
      if not useSteadyStateTwoPort "Model for dynamic energy balance"

  // Density at start values, used to compute initial values and start guesses
  parameter Modelica.Units.SI.Density rho_start=Medium.density(
    state=state_start) "Density, used to compute start and guess values";
  final parameter Medium.ThermodynamicState state_default = Medium.setState_pTX(
      T=Medium.T_default,
      p=Medium.p_default,
      X=Medium.X_default[1:Medium.nXi]) "Medium state at default values";
  // Density at medium default values, used to compute the size of control volumes
  final parameter Modelica.Units.SI.Density rho_default=Medium.density(
    state=state_default) "Density, used to compute fluid mass";
  final parameter Medium.ThermodynamicState state_start = Medium.setState_pTX(
      T=T_start,
      p=p_start,
      X=X_start[1:Medium.nXi]) "Medium state at start values";
  // See info section for why prescribedHeatFlowRate is used here.
  // The condition below may only be changed if StaticTwoPortConservationEquation
  // contains a correct solution for all foreseeable parameters/inputs.
  // See Buildings, issue 282 for a discussion.
  final parameter Boolean useSteadyStateTwoPort=(nPorts == 2) and
      (prescribedHeatFlowRate or (not allowFlowReversal)) and (
      energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState) and (
      massDynamics == Modelica.Fluid.Types.Dynamics.SteadyState) and (
      substanceDynamics == Modelica.Fluid.Types.Dynamics.SteadyState) and (
      traceDynamics == Modelica.Fluid.Types.Dynamics.SteadyState)
    "Flag, true if the model has two ports only and uses a steady state balance"
  // Outputs that are needed to assign the medium properties
  Modelica.Blocks.Interfaces.RealOutput hOut_internal(unit="J/kg")
    "Internal connector for leaving temperature of the component";
  Modelica.Blocks.Interfaces.RealOutput XiOut_internal[Medium.nXi](each unit="1")
    "Internal connector for leaving species concentration of the component";
  Modelica.Blocks.Interfaces.RealOutput COut_internal[Medium.nC](each unit="1")
    "Internal connector for leaving trace substances of the component";

  Buildings.HeatTransfer.Sources.PrescribedTemperature preTem(
    port(T(start=T_start)))
    "Port temperature"
  Modelica.Blocks.Sources.RealExpression portT(y=T) "Port temperature"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heaFloSen(
    port_a(T(start=T_start)),
    port_b(T(start=T_start)))
    "Heat flow sensor"
equation
  ///////////////////////////////////////////////////////////////////////////
  // asserts
  if not allowFlowReversal then
    assert(ports[1].m_flow > -m_flow_small,
  "In " + getInstanceName() + ": Model has flow reversal,
  but the parameter allowFlowReversal is set to false.
  m_flow_small    = " + String(m_flow_small) + "
  ports[1].m_flow = " + String(ports[1].m_flow) + "
");
  end if;
  // Actual definition of port variables.
  //
  // If the model computes the energy and mass balances as steady-state,
  // and if it has only two ports,
  // then we use the same base class as for all other steady state models.
  if useSteadyStateTwoPort then
  connect(steBal.port_a, ports[1])

  connect(steBal.port_b, ports[2])
    U=0;
    mXi=zeros(Medium.nXi);
    m=0;
    mC=zeros(Medium.nC);
    connect(hOut_internal,  steBal.hOut);
    connect(XiOut_internal, steBal.XiOut);
    connect(COut_internal,  steBal.COut);
  else
      connect(dynBal.ports, ports)
    connect(U,dynBal.UOut);
    connect(mXi,dynBal.mXiOut);
    connect(m,dynBal.mOut);
    connect(mC,dynBal.mCOut);
    connect(hOut_internal,  dynBal.hOut);
    connect(XiOut_internal, dynBal.XiOut);
    connect(COut_internal,  dynBal.COut);
  end if;

  connect(portT.y, preTem.T)
  connect(heaFloSen.port_b, preTem.port)
  connect(heaFloSen.Q_flow, steBal.Q_flow)
  connect(heaFloSen.Q_flow, dynBal.Q_flow)
else
  hOut = port_b.h_outflow;
end if;

Hence, for allowFlowReversal=true, if hOut
were to be used to compute the temperature that
drives heat transfer such as by conduction,
then the heat transfer would depend on upstream and the downstream
temperatures for small mass flow rates.
This can give wrong results. Consider for example a mass flow rate that is positive
but very close to zero. Suppose the upstream temperature is 20°C,
the downstream temperature is 10°C, and the heat port is
connected through a heat conductor to a boundary condition of 20°C.
Then, hOut = (port_b.h_outflow + port_a.h_outflow)/2 and hence
the temperature heatPort.T
is 15°C. Therefore, heat is added to the component.
As the mass flow rate is by assumption very small, the fluid that leaves the component
will have a very high temperature, violating the 2nd law.
To avoid this situation, if
prescribedHeatFlowRate=false, then the model

Buildings.Fluid.Interfaces.ConservationEquation
is used instead of

Buildings.Fluid.Interfaces.StaticTwoPortConservationEquation.

For simple models that uses this model, see

Buildings.Fluid.MixingVolumes.

", revisions="

June 18, 2024, by Michael Wetter:

Added start and nominal attributes
to avoid warnings in OpenModelica due to conflicting values.

This is for IBPSA, #1890.

October 24, 2022, by Michael Wetter:

Improved conversion from Xi to X so that it also works
with media that have reducedX=true.

See #1650.

September 18, 2020, by Michael Wetter:

Set start value for steBal.hOut so that T_start
can be used which is not known in that instance.

See #1397.

February 21, 2020, by Michael Wetter:

Changed icon to display its operating state.

This is for
#1294.

October 30, 2019 by Filip Jorissen:

Added getInstanceName() to flow
reversal check.
This if or
issue 1228.

October 19, 2017, by Michael Wetter:

Changed initialization of pressure from a constant to a parameter.

Removed partial keyword as this model is not partial.

Moved C_flow and use_C_flow to child classes.

This is for
Buildings, issue 1013.

April 11, 2017, by Michael Wetter:

Moved heat port to the extending classes to provide better comment.
Otherwise, the mixing volume without water input would have a comment
that says latent heat can be added at this port.

Removed blocks QSen_flow and
QLat_flow.

This is for issue
Buildings #704.

February 19, 2016 by Filip Jorissen:

Added outputs U, m, mXi, mC for being able to
check conservation of quantities.
This if or
issue 247.

January 22, 2016 by Michael Wetter:

Updated model to use the new parameter use_mWat_flow
rather than sensibleOnly.

January 17, 2016, by Michael Wetter:

Removed protected block masExc as
this revision introduces a conditional connector for the
moisture flow rate in the energy and mass balance models.
This change was done to use the same modeling concept for the
moisture input as is used for the trace substance input.

December 2, 2015, by Filip Jorissen:

Added conditional input C_flow for
handling trace substance insertions.

July 17, 2015, by Michael Wetter:

Added constant simplify_mWat_flow to remove dependencies of the pressure drop
calculation on the moisture balance.

July 1, 2015, by Filip Jorissen:

Set prescribedHeatFlowRate=prescribedHeatflowRate for

Buildings.Fluid.Interfaces.StaticTwoPortConservationEquation.
This results in equations that are solved more easily.
See

issue 282 for a discussion.

June 9, 2015 by Michael Wetter:

Set start value for heatPort.T and changed
type of T to Medium.Temperature rather than
Modelica.Units.SI.Temperature
to avoid an
error because of conflicting start values if
Buildings.Fluid.Chillers.Carnot_y
is translated using pedantic mode in Dymola 2016.
This is for
#426.

June 5, 2015, by Michael Wetter:

Moved assignment of dynBal.U.start
from instance dynBal to the actual model implementation.
This is required for a pedantic model check in Dymola 2016.
It addresses

issue 266.

May 6, 2015, by Michael Wetter:

Improved documentation and changed the test

 final parameter Boolean useSteadyStateTwoPort=(nPorts == 2) and
 prescribedHeatFlowRate and ...

to

 final parameter Boolean useSteadyStateTwoPort=(nPorts == 2) and
 (prescribedHeatFlowRate or (not allowFlowReversal)) and ...

The reason is that if there is no flow reversal, then

Buildings.Fluid.Interfaces.StaticTwoPortConservationEquation
computes hOut =  port_b.h_outflow;, and hence
it is correct to use hOut to compute
temperature-driven heat flow, such as by conduction or convection.
See also the model documentation.

This is for issue

#412.

February 5, 2015, by Michael Wetter:

Changed initalize_p from a parameter to a
constant. This is only required in finite volume models
of heat exchangers (to avoid consistent but redundant initial conditions)
and hence it should be set as a constant.

October 29, 2014, by Michael Wetter:

Made assignment of mFactor final, and changed computation of
density to use default medium states as are also used to compute the
specific heat capacity.

October 21, 2014, by Filip Jorissen:

Added parameter mFactor to increase the thermal capacity.

July 3, 2014, by Michael Wetter:

Added parameter initialize_p. This is required
to enable the coil models to initialize the pressure in the first
volume, but not in the downstream volumes. Otherwise,
the initial equations will be overdetermined, but consistent.
This change was done to avoid a long information message that appears
when translating models.

May 29, 2014, by Michael Wetter:

Removed undesirable annotation Evaluate=true.

February 11, 2014 by Michael Wetter:

Removed Q_flow and added QSen_flow.
This was done to clarify what is sensible and total heat flow rate
as part of the correction of issue
#197.

October 8, 2013 by Michael Wetter:

Removed propagation of show_V_flow
to instance steBal as it has no longer this parameter.

September 13, 2013 by Michael Wetter:

Renamed rho_nominal to rho_start
because this quantity is computed using start values and not
nominal values.

April 18, 2013 by Michael Wetter:

Removed the check of multiple connections to the same element
of a fluid port, as this check required the use of the deprecated
cardinality function.

February 7, 2012 by Michael Wetter:

Revised base classes for conservation equations in Buildings.Fluid.Interfaces.

September 17, 2011 by Michael Wetter:

Removed instance medium as this is already used in dynBal.
Removing the base properties led to 30% faster computing time for a solar thermal system
that contains many fluid volumes.

September 13, 2011 by Michael Wetter:

Changed in declaration of medium the parameter assignment
preferredMediumStates=true to
preferredMediumStates= not (energyDynamics == Modelica.Fluid.Types.Dynamics.SteadyState).
Otherwise, for a steady-state model, Dymola 2012 may differentiate the model to obtain T
as a state. See ticket Dynasim #13596.

July 26, 2011 by Michael Wetter:

Revised model to use new declarations from

Buildings.Fluid.Interfaces.LumpedVolumeDeclarations.

July 14, 2011 by Michael Wetter:

Added start values for mass and internal energy of dynamic balance
model.

May 25, 2011 by Michael Wetter:

Changed implementation of balance equation. The new implementation uses a different model if
exactly two fluid ports are connected, and in addition, the model is used as a steady-state
component. For this model configuration, the same balance equations are used as were used
for steady-state component models, i.e., instead of actualStream(...), the
inStream(...) formulation is used.
This changed required the introduction of a new parameter m_flow_nominal which
is used for smoothing in the steady-state balance equations of the model with two fluid ports.
This implementation also simplifies the implementation of

Buildings.Fluid.MixingVolumes.BaseClasses.PartialMixingVolumeWaterPort,
which now uses the same equations as this model.

Another revision was the removal of the parameter use_HeatTransfer as there is
no noticeable overhead in always having the heatPort connector present.

July 30, 2010 by Michael Wetter:

Added nominal value for mC to avoid wrong trajectory
when concentration is around 1E-7.
See also
https://trac.modelica.org/Modelica/ticket/393.

February 7, 2010 by Michael Wetter:

Simplified model and its base classes by removing the port data
and the vessel area.
Eliminated the base class PartialLumpedVessel.

October 12, 2009 by Michael Wetter:

Changed base class to

Buildings.Fluid.MixingVolumes.BaseClasses.ClosedVolume.

"),
    Icon(coordinateSystem(preserveAspectRatio=false, extent={{-100,-100},{100,
            100}}), graphics={
       Text(
          extent={{-60,-26},{56,-58}},
          textColor={255,255,255},
          textString="V=%V"),
        Text(
          extent={{-152,100},{148,140}},
          textString="%name",
          textColor={0,0,255}),
       Ellipse(
          extent={{-100,98},{100,-102}},
          lineColor={0,0,0},
          fillPattern=FillPattern.Sphere,
          fillColor=DynamicSelect({170,213,255}, min(1, max(0, (1-(T-273.15)/50)))*{28,108,200}+min(1, max(0, (T-273.15)/50))*{255,0,0})),
        Text(
          extent={{62,28},{-58,-22}},
          textColor={255,255,255},
          textString=DynamicSelect("", String(T-273.15, format=".1f")))}));
end PartialMixingVolume;


within Buildings.Fluid.MixingVolumes.BaseClasses.Validation;
model MixingVolumeHeatMoisturePort
  "Validation model for setting the initialization of the pressure for model with moisture port"
  extends Buildings.Fluid.MixingVolumes.BaseClasses.Validation.MixingVolumeHeatPortWater(
    redeclare package Medium = Buildings.Media.Air,
    redeclare Buildings.Fluid.MixingVolumes.BaseClasses.MixingVolumeHeatMoisturePort vol);

  Modelica.Blocks.Sources.Constant const[nEle](each k=0) "Zero input signal"
equation
  connect(const.y, vol.mWat_flow)
end MixingVolumeHeatMoisturePort;


within Buildings.Fluid.MixingVolumes.BaseClasses.Validation;
model MixingVolumeHeatPortAir
  "Validation model for setting the initialization of the pressure for air"
  extends Buildings.Fluid.MixingVolumes.BaseClasses.Validation.MixingVolumeHeatPortWater(
    redeclare package Medium = Buildings.Media.Air);
end MixingVolumeHeatPortAir;


within Buildings.Fluid.MixingVolumes.BaseClasses.Validation;
model MixingVolumeHeatPortWater
  "Validation model for setting the initialization of the pressure for water"
  extends Modelica.Icons.Example;

  replaceable package Medium = Buildings.Media.Water constrainedby
    Modelica.Media.Interfaces.PartialMedium "Medium model";

  parameter Integer nEle(min=2)= 3 "Number of volumes"

  replaceable Buildings.Fluid.MixingVolumes.BaseClasses.MixingVolumeHeatPort vol[nEle]
    constrainedby Buildings.Fluid.MixingVolumes.BaseClasses.MixingVolumeHeatPort(
    redeclare each package Medium = Medium,
    each energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    final initialize_p={(i == 1 and not Medium.singleState) for i in 1:nEle},
    each m_flow_nominal=1,
    each V=1,
    each nPorts=2) "Mixing volume"

  Buildings.Fluid.FixedResistances.PressureDrop res(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    dp_nominal=1000) "Pressure drop"

  Buildings.Fluid.Sources.Boundary_pT bou(
    redeclare package Medium = Medium,
    nPorts=1)
    "Boundary condition"

  Buildings.Fluid.FixedResistances.PressureDrop res1(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    dp_nominal=1000) "Pressure drop"

  Buildings.Fluid.Sources.Boundary_pT bou1(
    redeclare package Medium = Medium,
    nPorts=1)
    "Boundary condition"
equation
  connect(bou.ports[1], res.port_a)
  connect(res.port_b, vol[1].ports[1])
  for i in 1:nEle-1 loop
    connect(vol[i].ports[2], vol[i+1].ports[1]);
  end for;
  connect(res1.port_b, vol[nEle].ports[2])
  connect(bou1.ports[1], res1.port_a)
end MixingVolumeHeatPortWater;


Collection of validation models

within Buildings.Fluid.MixingVolumes.BaseClasses;
package Validation "Collection of validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Test model for heat transfer to volume

within Buildings.Fluid.MixingVolumes.Examples;
model MixingVolumeHeatConduction "Test model for heat transfer to volume"
  extends Modelica.Icons.Example;
    package Medium = Buildings.Media.Air;
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor theCon(G=10)
    "Thermal conductor"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heaFlo
    "Heat flow sensor"
  Buildings.HeatTransfer.Sources.FixedTemperature TAmb(T=293.15)
    "Ambient temperature"
  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    T=313.15,
    nPorts=1) "Flow source and sink"
  Modelica.Fluid.Sources.FixedBoundary bou(
    redeclare package Medium = Medium,
    T=303.15,
    nPorts=1) "Boundary condition"
  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    V=1,
    redeclare package Medium = Medium,
    m_flow_nominal=0.01,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=true,
    nPorts=2)
  Modelica.Blocks.Sources.Ramp ramp(
    duration=1,
    offset=1,
    height=-2)

  Modelica.Blocks.Math.Gain gain(k=0.01)
equation
  connect(TAmb.port, theCon.port_a)
  connect(heaFlo.port_b, vol.heatPort)
  connect(ramp.y, gain.u)
  connect(gain.y, sou.m_flow_in)
  connect(theCon.port_b, heaFlo.port_a)
  connect(sou.ports[1], vol.ports[1])
  connect(vol.ports[2], bou.ports[1])
end MixingVolumeHeatConduction;


within Buildings.Fluid.MixingVolumes.Examples;
model MixingVolumeMoistAir "Test model for mixing volume with moist air input"
  extends Modelica.Icons.Example;

  package Medium = Buildings.Media.Air;

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=0.001
    "Nominal mass flow rate";

  Buildings.Fluid.MixingVolumes.MixingVolumeMoistAir vol1(
    redeclare package Medium = Medium,
    V=1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=m_flow_nominal,
    nPorts=2)                      "Volume"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor TSen
    "Temperature sensor"
  Modelica.Blocks.Sources.Constant XSet(k=0.005)
    "Set point for water mass fraction"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHeaFlo
  Modelica.Blocks.Sources.Constant TSet(k=273.15 + 20)
    "Set point for temperature"
  Buildings.Utilities.Psychrometrics.pW_X humRat(use_p_in=false)
    "Conversion from humidity ratio to partial water vapor pressure"
  Buildings.Utilities.Psychrometrics.TDewPoi_pW dewPoi "Dew point temperature"
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heatFlowSensor
  Modelica.Blocks.Continuous.Integrator QSen "Sensible heat transfer"
  Modelica.Blocks.Continuous.Integrator QLat "Enthalpy of extracted water"
  Buildings.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    nPorts=1,
    T=293.15)
  Buildings.Fluid.Sources.Boundary_pT sin(        redeclare package Medium =
        Medium,
    T=293.15,
    nPorts=1)
  Buildings.Controls.Continuous.LimPID PI(
    Ni=0.1,
    yMax=1000,
    k=1,
    Ti=1,
    Td=1,
    wd=0,
    yMin=-1000)
  Buildings.Controls.Continuous.LimPID PI1(
    Ni=0.1,
    Ti=1,
    k=10,
    yMax=1,
    yMin=-1,
    Td=1)
  Buildings.Fluid.Sensors.MassFlowRate mIn_flow(redeclare package Medium =
        Medium)
  Buildings.Fluid.Sensors.MassFlowRate mOut_flow(redeclare package Medium =
        Medium)
  Modelica.Blocks.Math.Add dM_flow(k2=-1)
  Modelica.Blocks.Math.Gain gai(k=200)
  Modelica.Blocks.Math.Gain gai1(k=0.1)

  Buildings.Fluid.FixedResistances.PressureDrop res1(
    redeclare package Medium = Medium,
    from_dp=true,
    dp_nominal=2.5,
    m_flow_nominal=m_flow_nominal)
  Sensors.LatentEnthalpyFlowRate senLatEnt(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    tau=0,
    initType=Modelica.Blocks.Types.Init.SteadyState) "Latent enthalpy inflow"
  Sensors.LatentEnthalpyFlowRate senLatEnt1(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    tau=0,
    initType=Modelica.Blocks.Types.Init.SteadyState) "Latent enthalpy outflow"
  Modelica.Blocks.Math.Add add
equation
  connect(preHeaFlo.port, heatFlowSensor.port_a)
  connect(heatFlowSensor.Q_flow, QSen.u)
  connect(TSet.y, PI.u_s)
  connect(TSen.T, PI.u_m)
  connect(XSet.y, PI1.u_s)
  connect(mOut_flow.m_flow, dM_flow.u1)
  connect(mIn_flow.m_flow, dM_flow.u2)
  connect(gai.y, preHeaFlo.Q_flow)
  connect(PI1.y, gai1.u)
  connect(gai1.y, vol1.mWat_flow)
  connect(vol1.X_w, PI1.u_m)
  connect(vol1.X_w, humRat.X_w)
  connect(sou.ports[1], mIn_flow.port_a)
  connect(heatFlowSensor.port_b, vol1.heatPort)
  connect(TSen.port, vol1.heatPort)
  connect(PI.y, gai.u)
  connect(humRat.p_w, dewPoi.p_w)
  connect(mOut_flow.port_b, res1.port_a)
  connect(res1.port_b, sin.ports[1])
  connect(mIn_flow.port_b, senLatEnt.port_a)
  connect(senLatEnt.port_b, vol1.ports[1])
  connect(vol1.ports[2], senLatEnt1.port_a)
  connect(senLatEnt1.port_b, mOut_flow.port_a)
  connect(add.y, QLat.u)
  connect(add.u1, senLatEnt.H_flow)
  connect(senLatEnt1.H_flow, add.u2)
end MixingVolumeMoistAir;


Test model for heat transfer to volume

within Buildings.Fluid.MixingVolumes.Examples;
model MixingVolumePrescribedHeatFlowRate
  "Test model for heat transfer to volume"
  extends Modelica.Icons.Example;
    package Medium = Buildings.Media.Air;
  Modelica.Thermal.HeatTransfer.Sensors.HeatFlowSensor heaFlo
    "Heat flow sensor"
  Modelica.Fluid.Sources.MassFlowSource_T sou(
    nPorts=1,
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    T=313.15) "Flow source and sink"
  Modelica.Fluid.Sources.FixedBoundary bou(
    redeclare package Medium = Medium,
    nPorts=1,
    T=303.15) "Boundary condition"
  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    V=1,
    nPorts=2,
    redeclare package Medium = Medium,
    m_flow_nominal=0.01,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=true,
    prescribedHeatFlowRate=true)
  Modelica.Blocks.Sources.Ramp ramp(
    duration=1,
    offset=1,
    height=-2)

  Modelica.Blocks.Math.Gain gain(k=0.01)
  Modelica.Blocks.Sources.Constant const(k=0)
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHeaFlo
    "Prescribed heat flow rate"
equation
  connect(sou.ports[1], vol.ports[1])
  connect(ramp.y, gain.u)
  connect(gain.y, sou.m_flow_in)
  connect(vol.ports[2], bou.ports[1])
  connect(preHeaFlo.port, heaFlo.port_a)
  connect(preHeaFlo.Q_flow, const.y)
  connect(heaFlo.port_b, vol.heatPort)
end MixingVolumePrescribedHeatFlowRate;


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


within Buildings.Fluid.MixingVolumes.Validation;
model CoupledVolumesAir
  "Validation model for two coupled volumes with air"
  extends Buildings.Fluid.MixingVolumes.Validation.CoupledVolumesWater(
    redeclare package Medium = Buildings.Media.Air);
end CoupledVolumesAir;


within Buildings.Fluid.MixingVolumes.Validation;
model CoupledVolumesGlycol47
  "Validation model for two coupled volumes with glycol"
  extends Buildings.Fluid.MixingVolumes.Validation.CoupledVolumesWater(
    redeclare package Medium = Modelica.Media.Incompressible.Examples.Glycol47);
end CoupledVolumesGlycol47;


within Buildings.Fluid.MixingVolumes.Validation;
model CoupledVolumesSpecializedAirPerfectGas
  "Validation model for two coupled volumes with air as a perfect gas"
  extends Buildings.Fluid.MixingVolumes.Validation.CoupledVolumesWater(
    redeclare package Medium =
        Buildings.Media.Specialized.Air.PerfectGas);
end CoupledVolumesSpecializedAirPerfectGas;


within Buildings.Fluid.MixingVolumes.Validation;
model CoupledVolumesSpecializedWaterConstantProperties_pT
  "Validation model for two coupled volumes with water with constant properties"
  extends Buildings.Fluid.MixingVolumes.Validation.CoupledVolumesWater(
    redeclare package Medium =
        Buildings.Media.Specialized.Water.ConstantProperties_pT);
end CoupledVolumesSpecializedWaterConstantProperties_pT;


within Buildings.Fluid.MixingVolumes.Validation;
model CoupledVolumesSpecializedWaterTemperatureDependentDensity
  "Validation model for two coupled volumes with water with temperature dependent density"
  extends Buildings.Fluid.MixingVolumes.Validation.CoupledVolumesWater(
    redeclare package Medium =
        Buildings.Media.Specialized.Water.TemperatureDependentDensity);
end CoupledVolumesSpecializedWaterTemperatureDependentDensity;


within Buildings.Fluid.MixingVolumes.Validation;
model CoupledVolumesWater
  "Validation model for two coupled volumes with water"
  extends Modelica.Icons.Example;

  replaceable package Medium = Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium "Medium model";

  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    redeclare package Medium = Medium,
    nPorts=2,
    m_flow_nominal=1,
    V=1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
  Buildings.Fluid.MixingVolumes.MixingVolume vol1(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    V=1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nPorts=1)
  Buildings.Fluid.Sources.Boundary_pT bou(
    redeclare package Medium = Medium,
    nPorts=1)
    "Pressure boundary condition"
  Buildings.Fluid.FixedResistances.PressureDrop res(
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    dp_nominal=100) "Resistance to decouple initialization of pressure state"
equation
  connect(bou.ports[1], res.port_a)
  connect(res.port_b, vol.ports[1])
  connect(vol.ports[2], vol1.ports[1])
end CoupledVolumesWater;


Test model for mixing volumes

within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolume "Test model for mixing volumes"
  extends Modelica.Icons.Example;

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

    Modelica.Blocks.Sources.Ramp P(
    duration=0.5,
    startTime=0.5,
    height=-10,
    offset=101330)
  Buildings.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    T=293.15,
    use_p_in=true,
    nPorts=3)
  Buildings.Fluid.Sources.Boundary_pT sin(
    redeclare package Medium = Medium,
    nPorts=3,
    use_p_in=false,
    p=101325,
    T=283.15)
  Buildings.Fluid.FixedResistances.PressureDrop res1(
    redeclare package Medium = Medium,
    from_dp=true,
    m_flow_nominal=2,
    dp_nominal=2.5)
  MixingVolumes.MixingVolume vol1(
    redeclare package Medium = Medium,
    V=0.1,
    nPorts=2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=2)
  Buildings.Fluid.FixedResistances.PressureDrop res2(
    redeclare package Medium = Medium,
    from_dp=true,
    m_flow_nominal=2,
    dp_nominal=2.5)
  Buildings.Fluid.FixedResistances.PressureDrop res11(
    redeclare package Medium = Medium,
    from_dp=true,
    m_flow_nominal=2,
    dp_nominal=2.5)
  Buildings.Fluid.FixedResistances.PressureDrop res12(
    redeclare package Medium = Medium,
    from_dp=true,
    m_flow_nominal=2,
    dp_nominal=2.5)
  Modelica.Fluid.Vessels.ClosedVolume vol(
    redeclare package Medium = Medium,
    massDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    V=0.1,
    nPorts=2,
    h_start=45300.945,
    use_portsData=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
  Buildings.Utilities.Diagnostics.CheckEquality cheEqu1
    "Check for equality of results"
  Buildings.Fluid.Sensors.EnthalpyFlowRate entFloRat(
    redeclare package Medium = Medium,
    m_flow_nominal=2) "Enthalpy flow rate"
  Buildings.Fluid.Sensors.EnthalpyFlowRate entFloRat1(
    redeclare package Medium = Medium,
    m_flow_nominal=2) "Enthalpy flow rate"
  Buildings.Fluid.MixingVolumes.MixingVolumeMoistAir vol2(
    redeclare package Medium = Medium,
    V=0.1,
    nPorts=2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=2)
  Buildings.Fluid.FixedResistances.PressureDrop res21(
    redeclare package Medium = Medium,
    from_dp=true,
    m_flow_nominal=2,
    dp_nominal=2.5)
  Buildings.Fluid.FixedResistances.PressureDrop res22(
    redeclare package Medium = Medium,
    from_dp=true,
    m_flow_nominal=2,
    dp_nominal=2.5)
  Buildings.Utilities.Diagnostics.CheckEquality cheEqu2
    "Check for equality of results"
  Buildings.Fluid.Sensors.EnthalpyFlowRate entFloRat2(
    redeclare package Medium = Medium,
    m_flow_nominal=2) "Enthalpy flow rate"
    Modelica.Blocks.Sources.Constant zero(k=0)

  inner Modelica.Fluid.System system
equation
  connect(P.y, sou.p_in)
  connect(res2.port_a, entFloRat.port_b)
  connect(entFloRat2.H_flow, cheEqu2.u2)
  connect(zero.y, vol2.mWat_flow)
  connect(sou.ports[1], res1.port_a)
  connect(sou.ports[2], res11.port_a)
  connect(sou.ports[3], res21.port_a)
  connect(sin.ports[1], res2.port_b)
  connect(sin.ports[2], res12.port_b)
  connect(res22.port_b, sin.ports[3])
  connect(res1.port_b, vol.ports[1])
  connect(vol.ports[2], entFloRat.port_a)
  connect(res11.port_b, vol1.ports[1])
  connect(vol1.ports[2], entFloRat1.port_a)
  connect(res21.port_b, vol2.ports[1])
  connect(vol2.ports[2], entFloRat2.port_a)
  connect(entFloRat2.port_b, res22.port_a)
  connect(entFloRat1.port_b, res12.port_a)
  connect(entFloRat.H_flow, cheEqu1.u1)
  connect(entFloRat.H_flow, cheEqu2.u1)
  connect(entFloRat1.H_flow, cheEqu1.u2)
end MixingVolume;


within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeAdiabaticCooling
  "Validation model for mixing volume with adiabatic cooling"
  extends Modelica.Icons.Example;

  package Medium = Buildings.Media.Air "Medium model";
  MixingVolumeMoistAir volSim(
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=1,
    V=1,
    final simplify_mWat_flow=true,
    nPorts=1)
    "Mixing volume with water vapor input and simplified water balance"
  MixingVolumeMoistAir volExa(
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=1,
    V=1,
    final simplify_mWat_flow=false,
    nPorts=1) "Mixing volume with water vapor input and exact water balance"
  Modelica.Blocks.Sources.Constant mWatFlo(k=0.001) "Water mass flow rate "
  Modelica.Blocks.Sources.RealExpression relErr(
    y=(volSim.heatPort.T - 20)
      /(if abs(volExa.heatPort.T - 20) < 1E-5 then 1 else (volExa.heatPort.T - 20)))
    "Relative error in the temperature difference"
  Buildings.Fluid.Sources.Boundary_pT bou(redeclare package Medium = Medium, nPorts=2)
    "Fixed pressure boundary condition"

equation
  connect(volSim.mWat_flow, mWatFlo.y)
  connect(volExa.mWat_flow, mWatFlo.y)
  connect(bou.ports[1], volSim.ports[1])
  connect(bou.ports[2], volExa.ports[1])
end MixingVolumeAdiabaticCooling;


Validation model for mixing volume with heat input and flow reversal. This model validates the use of the mixing volume with air flowing into and out of the volume
and sensible heat added to the volume.

within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeHeatReverseFlow
  "Validation model for mixing volume with heat input and flow reversal"
  extends
    Buildings.Fluid.MixingVolumes.Validation.BaseClasses.MixingVolumeReverseFlow(
      gain(k=10));

  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHeaDyn
    "Prescribed heat flow rate"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHeaSte
    "Prescribed heat flow rate"
equation
  connect(gain.y, preHeaDyn.Q_flow)
  connect(gain.y, preHeaSte.Q_flow)
  connect(preHeaDyn.port, volDyn.heatPort)
  connect(preHeaSte.port, volSte.heatPort)
end MixingVolumeHeatReverseFlow;


Validation model for mixing volume with heat input and flow reversal and prescribed heat flow rate. This model is identical to

Buildings.Fluid.MixingVolumes.Validation.MixingVolumeHeatReverseFlow,
except that the steady state volume volSte
is configured to have a prescribed heat flow rate,
which is in this case zero as the heat port is not connected.
This configures volSte to use the two port
steady state heat and mass balance model

Buildings.Fluid.Interfaces.StaticTwoPortConservationEquation.

within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeHeatReverseFlowPrescribedHeatFlowRate
  "Validation model for mixing volume with heat input and flow reversal and prescribed heat flow rate"
  extends MixingVolumeHeatReverseFlow(
    prescribedHeatFlowRate=true);
end MixingVolumeHeatReverseFlowPrescribedHeatFlowRate;


within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeInitialization "Test model for mixing volume initialization"
  extends Modelica.Icons.Example;
 package Medium = Buildings.Media.Air;

  Buildings.Fluid.Sources.Boundary_pT sou1(redeclare package Medium =
        Medium,
    p=101330,
    nPorts=1,
    T=293.15)
  Buildings.Fluid.Sources.Boundary_pT sin1(redeclare package Medium =
        Medium,
    p=101320,
    nPorts=1,
    T=293.15)
  Modelica.Fluid.Pipes.StaticPipe pipe1(
    redeclare package Medium = Medium,
    length=1,
    diameter=0.25,
    flowModel(m_flow_nominal=2))
  Modelica.Fluid.Pipes.StaticPipe pipe2(
    redeclare package Medium = Medium,
    length=1,
    diameter=0.25,
    flowModel(m_flow_nominal=2))
  MixingVolumes.MixingVolume vol1(
    redeclare package Medium = Medium,
    V=0.1,
    nPorts=2,
    m_flow_nominal=2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)

  inner Modelica.Fluid.System system
equation
  connect(sou1.ports[1], pipe1.port_a)
  connect(pipe1.port_b, vol1.ports[1])
  connect(vol1.ports[2], pipe2.port_a)
  connect(pipe2.port_b, sin1.ports[1])
end MixingVolumeInitialization;


within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeMassFlow "Test model for mass flow into and out of volume"
  extends Modelica.Icons.Example;
 package Medium = Buildings.Media.Air "Medium model";

  parameter Modelica.Units.SI.PressureDifference dp_nominal=10
    "Nominal pressure drop";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=0.5
    "Nominal mass flow rate";

  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    nPorts=1,
    use_m_flow_in=false,
    m_flow=m_flow_nominal,
    T=313.15) "Flow source and sink"
  Sources.Boundary_pT bou(
    redeclare package Medium = Medium,
    T=303.15,
    nPorts=1) "Boundary condition"
  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    V=1,
    redeclare package Medium = Medium,
    nPorts=2,
    allowFlowReversal=false,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)

equation
  connect(sou.ports[1], vol.ports[1])
  connect(bou.ports[1], vol.ports[2])
end MixingVolumeMassFlow;


within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeMFactor
  "A check for verifying the implementation of the parameter mSenFac"
  extends Buildings.Fluid.MixingVolumes.Validation.MixingVolumeMassFlow(
  sou(X={0.02,0.98},
      T=Medium.T_default),
  vol(mSenFac=10),
    bou(nPorts=3));
  Buildings.Fluid.MixingVolumes.MixingVolume volMFactor(
    redeclare package Medium = Medium,
    mSenFac=10,
    V=1,
    nPorts=2,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Mixing volume using mSenFac = 10"
  Buildings.Fluid.MixingVolumes.MixingVolume vol1(
    redeclare package Medium = Medium,
    V=10,
    nPorts=2,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "MixingVolume with V = 10 instead of mSenFac = 10"
  Buildings.Fluid.Sources.MassFlowSource_T boundaryMFactor(
    redeclare package Medium = Medium,
    T=300,
    nPorts=1,
    m_flow=1,
    X={0.02,0.98}) "Flow source for mixing volume using mSenFac"
  Buildings.Fluid.Sources.MassFlowSource_T boundary(
    redeclare package Medium = Medium,
    T=300,
    nPorts=1,
    m_flow=1,
    X={0.02,0.98}) "Flow source for mixing volume using larger volume"
equation
  connect(boundaryMFactor.ports[1],volMFactor. ports[1])
  connect(boundary.ports[1], vol1.ports[1])
  connect(bou.ports[2], volMFactor.ports[2])
  connect(bou.ports[3], vol1.ports[2])
end MixingVolumeMFactor;


Validation model for mixing volume with moisture input and flow reversal. This model validates the use of the mixing volume with air flowing into and out of the volume
and moisture added to the volume.

within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeMoistureReverseFlow
  "Validation model for mixing volume with moisture input and flow reversal"
  extends
    Buildings.Fluid.MixingVolumes.Validation.BaseClasses.MixingVolumeReverseFlow(
    gain(k=0.005),
    redeclare MixingVolumeMoistAir volDyn,
    redeclare MixingVolumeMoistAir volSte);

equation
  connect(volDyn.mWat_flow, gain.y)
  connect(gain.y, volSte.mWat_flow)
end MixingVolumeMoistureReverseFlow;


Validation model for mixing volume with moisture input and flow reversal and prescribed heat flow rate. This model is identical to

Buildings.Fluid.MixingVolumes.Validation.MixingVolumeMoistureReverseFlow,
except that the steady state volume volSte
is configured to have a prescribed heat flow rate,
which is in this case zero as the heat port is not connected.
This configures volSte to use the two port
steady state heat and mass balance model

Buildings.Fluid.Interfaces.StaticTwoPortConservationEquation.

within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeMoistureReverseFlowPrescribedHeatFlowRate
  "Validation model for mixing volume with moisture input and flow reversal and prescribed heat flow rate"
  extends MixingVolumeMoistureReverseFlow(
    prescribedHeatFlowRate=true);
end MixingVolumeMoistureReverseFlowPrescribedHeatFlowRate;


within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeSteadyStateMass "Test model for steady state mass dynamics"
  extends Modelica.Icons.Example;
  package Medium = Buildings.Media.Air;
  Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    nPorts=1) "Flow source and sink"
  Sources.Boundary_pT bou(
    redeclare package Medium = Medium,
    nPorts=1) "Boundary condition"
  Buildings.Fluid.MixingVolumes.MixingVolume vol(
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    V=1,
    redeclare package Medium = Medium,
    m_flow_nominal=0.01,
    massDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=true,
    nPorts=2,
    mSenFac=2)
    "Mixing volume with steady state mass dynamics"
  Modelica.Blocks.Sources.Ramp ramp(
    duration=1,
    offset=1,
    height=-2) "Ramp input"

  Modelica.Blocks.Math.Gain gain(k=0.01) "Gain for nominal mass flow rate"
  FixedResistances.PressureDrop res(
    redeclare package Medium = Medium,
    m_flow_nominal=0.01,
    dp_nominal=1000) "Pressure drop"
equation
  connect(ramp.y, gain.u)
  connect(gain.y, sou.m_flow_in)
  connect(sou.ports[1], vol.ports[1])
  connect(vol.ports[2], res.port_a)
  connect(res.port_b, bou.ports[1])
end MixingVolumeSteadyStateMass;


within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeTraceSubstance
  "Test model for mixing volume with trace substance input"
  extends Modelica.Icons.Example;
 package Medium = Buildings.Media.Air(extraPropertiesNames={"CO2"})
    "Medium model";

  parameter Modelica.Units.SI.Pressure dp_nominal=10 "Nominal pressure drop";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=0.5
    "Nominal mass flow rate";

  Modelica.Fluid.Sources.MassFlowSource_T sou(
    redeclare package Medium = Medium,
    nPorts=1,
    use_m_flow_in=false,
    m_flow=m_flow_nominal,
    T=313.15) "Flow source and sink"
  Sources.Boundary_pT bou(
    redeclare package Medium = Medium,
    T=303.15,
    nPorts=2) "Boundary condition"
  Buildings.Fluid.MixingVolumes.MixingVolume volDyn(
    redeclare package Medium = Medium,
    V=1,
    nPorts=2,
    allowFlowReversal=false,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    use_C_flow=true) "Volume with dynamic balance"

  Modelica.Blocks.Sources.Constant C_flow(k=m_flow_nominal/1000)
    "Trace substance mass flow rate"
  Modelica.Fluid.Sources.MassFlowSource_T sou1(
    redeclare package Medium = Medium,
    nPorts=1,
    use_m_flow_in=false,
    m_flow=m_flow_nominal,
    T=313.15) "Flow source and sink"
  Buildings.Fluid.MixingVolumes.MixingVolume volSte(
    redeclare package Medium = Medium,
    V=1,
    nPorts=2,
    m_flow_nominal=m_flow_nominal,
    use_C_flow=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=false) "Volume with steady-state balance"
equation
  connect(sou.ports[1], volDyn.ports[1])
  connect(C_flow.y, volDyn.C_flow[1])
  connect(sou1.ports[1], volSte.ports[1])
  connect(C_flow.y, volSte.C_flow[1])
  connect(volSte.ports[2], bou.ports[1])
  connect(volDyn.ports[2], bou.ports[2])
end MixingVolumeTraceSubstance;


Validation model for mixing volume with trace substance input and flow reversal. This model validates the use of the mixing volume with air flowing into and out of the volume
and trace substances added to the volume.

within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeTraceSubstanceReverseFlow
  "Validation model for mixing volume with trace substance input and flow reversal"
  extends
    Buildings.Fluid.MixingVolumes.Validation.BaseClasses.MixingVolumeReverseFlow(
    Medium(extraPropertiesNames={"CO2"}),
    volDyn(use_C_flow=true),
    volSte(use_C_flow=true),
    gain(k=1/1000),
    bou(C={0.003}));

equation
  connect(gain.y, volSte.C_flow[1])
  connect(gain.y, volDyn.C_flow[1])
end MixingVolumeTraceSubstanceReverseFlow;


Validation model for mixing volume with trace substance input and flow reversal, and prescribed heat flow rate. This model is identical to

Buildings.Fluid.MixingVolumes.Validation.MixingVolumeTraceSubstanceReverseFlow,
except that the steady state volume volSte
is configured to have a prescribed heat flow rate,
which is in this case zero as the heat port is not connected.
This configures volSte to use the two port
steady state heat and mass balance model

Buildings.Fluid.Interfaces.StaticTwoPortConservationEquation.

within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeTraceSubstanceReverseFlowPrescribedHeatFlowRate
  "Validation model for mixing volume with trace substance input and flow reversal, and prescribed heat flow rate"
  extends MixingVolumeTraceSubstanceReverseFlow(
    prescribedHeatFlowRate=true);
end MixingVolumeTraceSubstanceReverseFlowPrescribedHeatFlowRate;


within Buildings.Fluid.MixingVolumes.Validation;
model MixingVolumeZeroFlow
  "Mixing volume verification around zero flow with heat exchange"
  extends Modelica.Icons.Example;
  package Medium = Buildings.Media.Water;
  Buildings.Fluid.MixingVolumes.MixingVolume volNonLinSys(
    nPorts=2,
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    V=1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=false)
    "Steady state mixing volume requiring solution of non-linear system"
  Buildings.Fluid.Sources.MassFlowSource_T sou2(
    nPorts=1,
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    use_T_in=true) "Source"
  Buildings.Fluid.Sources.Boundary_pT sin(nPorts=4, redeclare package Medium =
        Medium) "Sink"
  Modelica.Blocks.Sources.Ramp ramp_m_flow(
    height=-1,
    duration=1,
    offset=1) "Mass flow rate ramp input"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea2
    "Prescribed heat flow"
  Modelica.Blocks.Sources.RealExpression reaExp(y=(290 - volNonLinSys.heatPort.T)
        /100*volNonLinSys.heatPort.T^(3/5)*time)
    "Non-linear thermal resistance equation"
  Buildings.HeatTransfer.Sources.PrescribedTemperature preTem
    "Prescribed temperature"
  Modelica.Blocks.Sources.Cosine cos1(
    f=1,
    offset=283.15,
    amplitude=0.001) "Cosine input"
  Buildings.Fluid.MixingVolumes.MixingVolume volT(
    nPorts=2,
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    V=1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=false)
    "Steady state mixing volume with prescribed temperature input"
  Buildings.Fluid.Sources.MassFlowSource_T sou3(
    nPorts=1,
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    use_T_in=true) "Source"
  Buildings.Fluid.MixingVolumes.MixingVolume volLinSys(
    nPorts=2,
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    V=1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=false,
    prescribedHeatFlowRate=false)
    "Steady state mixing volume requiring solution of linear system"
  Buildings.Fluid.Sources.MassFlowSource_T sou4(
    nPorts=1,
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    use_T_in=true) "Source"
  Modelica.Thermal.HeatTransfer.Components.ThermalResistor theRes(R=0.001)
    "Thermal resistor for creating linear system"
  Modelica.Blocks.Sources.Ramp ramp_T(
    duration=2,
    offset=283.15,
    height=0) "Temperature ramp input"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedHeatFlow preHea1
    "Prescribed heat flow"
  Buildings.Fluid.MixingVolumes.MixingVolume volQflow(
    nPorts=2,
    redeclare package Medium = Medium,
    m_flow_nominal=1,
    V=1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    allowFlowReversal=false,
    prescribedHeatFlowRate=true)
    "Steady state mixing volume with fixed heat flow rate input"
  Buildings.Fluid.Sources.MassFlowSource_T sou1(
    nPorts=1,
    redeclare package Medium = Medium,
    use_m_flow_in=true,
    use_T_in=true) "Source"
  Modelica.Blocks.Routing.RealPassThrough reaPasThr
    "Real pass through for unit conversion"
equation
  connect(sou2.ports[1], volNonLinSys.ports[1])
  connect(volNonLinSys.ports[2], sin.ports[1])
  connect(reaExp.y, preHea2.Q_flow)
  connect(preTem.T, cos1.y)
  connect(volT.ports[1],sou3. ports[1])
  connect(volT.ports[2], sin.ports[2])
  connect(volT.heatPort, preTem.port)
  connect(sou4.ports[1], volLinSys.ports[1])
  connect(volLinSys.ports[2], sin.ports[3])
  connect(theRes.port_a, volLinSys.heatPort)
  connect(theRes.port_b, preTem.port)
  connect(volNonLinSys.heatPort, preHea2.port)
  connect(volQflow.heatPort, preHea1.port)
  connect(sou1.ports[1], volQflow.ports[1])
  connect(volQflow.ports[2], sin.ports[4])
  connect(ramp_m_flow.y, sou1.m_flow_in)
  connect(ramp_m_flow.y, sou2.m_flow_in)
  connect(ramp_m_flow.y, sou3.m_flow_in)
  connect(ramp_m_flow.y, sou4.m_flow_in)
  connect(ramp_T.y, sou1.T_in)
  connect(ramp_T.y, sou2.T_in)
  connect(ramp_T.y, sou3.T_in)
  connect(ramp_T.y, sou4.T_in)
  connect(reaPasThr.y, preHea1.Q_flow)
  connect(reaPasThr.u, ramp_m_flow.y)
end MixingVolumeZeroFlow;