ConvergingTee

model ConvergingTee
    import SI = Modelica.SIunits;

    parameter SI.Length Dc = 0.005 "Diameter of main passage";
    parameter SI.Length Ds = 0.005 "Diameter of branch";
    parameter Modelica.Thermal.FluidHeatFlow.Media.Medium medium = Modelica.Thermal.FluidHeatFlow.Media.Medium() "Medium in the component"
        annotation (choicesAllMatching = true);
    parameter SI.Temperature T0(start = 293.15, displayUnit = "degC") "Initial temperature of medium"
        annotation (Dialog(enable = Modelica.Constants.small < m));
    parameter Boolean T0fixed = false "Initial temperature guess value or fixed"
        annotation (
            choices(checkBox = true),
            Dialog(enable = Modelica.Constants.small < m));
    output SI.Temperature T(start = T0, fixed = T0fixed) "Outlet temperature of medium";
    parameter Real frictionLoss(min = 0, max = 1, start = 0) "Part of friction losses fed to medium";
    Modelica.Thermal.FluidHeatFlow.Interfaces.FlowPort_b flowPort_c(final medium = medium) "Outlet port c"
        annotation (Placement(
            visible = true,
            transformation(
                extent = {
                    {-110, -10}, 
                    {-90, 10}},
                rotation = 0),
            iconTransformation(
                extent = {
                    {-110, -10}, 
                    {-90, 10}},
                rotation = 0)));
    Modelica.Thermal.FluidHeatFlow.Interfaces.FlowPort_a flowPort_st(final medium = medium) "Inlet port straight passage"
        annotation (Placement(
            visible = true,
            transformation(
                extent = {
                    {90, -10}, 
                    {110, 10}},
                rotation = 0),
            iconTransformation(
                extent = {
                    {90, -10}, 
                    {110, 10}},
                rotation = 0)));
    Modelica.Thermal.FluidHeatFlow.Interfaces.FlowPort_a flowPort_s(final medium = medium) "Inlet port side branch"
        annotation (Placement(
            visible = true,
            transformation(
                extent = {
                    {-10, -90}, 
                    {10, -110}},
                rotation = 0),
            iconTransformation(
                extent = {
                    {-10, 110}, 
                    {10, 90}},
                rotation = 0)));
    parameter Boolean enableZetaOutput = false "Enable zeta output"
        annotation (choices(checkBox = true));
    Modelica.Blocks.Interfaces.RealOutput zeta_st if enableZetaOutput "zetacst"
        annotation (Placement(transformation(
            origin = {100, -100},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = 0)));
    Modelica.Blocks.Interfaces.RealOutput zeta_s if enableZetaOutput "zetacs"
        annotation (Placement(transformation(
            origin = {100, 100},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = -90)));
    Modelica.Blocks.Interfaces.RealOutput QsQc if enableZetaOutput "Qs/Qc"
        annotation (Placement(transformation(
            origin = {-100, -100},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = -90)));
    parameter Boolean useHeatPort = false "Enable HeatPort"
        annotation (
            Evaluate = true,
            HideResult = true,
            choices(checkBox = true));
    Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort(T = T, Q_flow = Q_flowHeatPort) if useHeatPort annotation (Placement(transformation(extent = {
        {-10, -110}, 
        {10, -90}})));
protected
    SI.SpecificEnthalpy h(start = medium.cp * T0) "Medium's specific enthalpy";
    Modelica.SIunits.HeatFlowRate Q_flowHeatPort "Heat flow at conditional heatPort";
    Real Fc = 0.25 * (Dc * Dc * Modelica.Constants.pi);
    Real Fs = 0.25 * (Ds * Ds * Modelica.Constants.pi);
    Real dpstc "Pressure drop st->c";
    Real dpsc "Pressure drop s->c";
    Real zetacst "zeta main passage";
    Real zetacs "zeta side branch";
    Modelica.SIunits.VolumeFlowRate Vflowst(start = 0) "Volume flow at st";
    Modelica.SIunits.VolumeFlowRate Vflows(start = 0) "Volume flow at s";
    Modelica.SIunits.VolumeFlowRate Vflowc(start = 0) "Volume flow at c";
    Real Qflowst;
    Real Qflows;
    Real A;
equation
    if enableZetaOutput then 
        zeta_st = zetacst;
        zeta_s = zetacs;
        QsQc = Vflows / max(Vflowc, Modelica.Constants.small);
    end if;
    if not useHeatPort then 
        Q_flowHeatPort = 0;
    end if;
    if noEvent(Modelica.Constants.small < Vflowc) then 
        if noEvent(Fs / Fc <= 0.35) then 
            A = 1;
        else 
            if noEvent(Vflows / Vflowc <= 0.4) then 
                A = 0.9 * (1 - Vflows / Vflowc);
            else 
                A = 0.55;
            end if;
        end if;
        zetacs = A * (1 + (Vflows * Fc / Vflowc / Fs) ^ 2 - 2 * (1 - Vflows * Fc / Vflowc / Fs) ^ 2);
        zetacst = 1.55 * Vflows / Vflowc - (Vflows / Vflowc) ^ 2;
    else 
        A = 1;
        zetacs = 0;
        zetacst = 0;
    end if;
    flowPort_c.H_flow + flowPort_st.H_flow + flowPort_s.H_flow + Qflowst + Qflows + Q_flowHeatPort = 0;
    flowPort_c.m_flow + flowPort_st.m_flow + flowPort_s.m_flow = 0;
    h = medium.cp * T;
    Qflows = frictionLoss * Vflows * dpsc;
    Qflowst = frictionLoss * Vflowst * dpstc;
    Vflowc = -flowPort_c.m_flow / medium.rho;
    Vflows = flowPort_s.m_flow / medium.rho;
    Vflowst = flowPort_st.m_flow / medium.rho;
    dpsc = 0.5 * (Vflowc ^ 2 / Fc ^ 2 * medium.rho * zetacs);
    dpsc = flowPort_s.p - flowPort_c.p;
    dpstc = 0.5 * (Vflowc ^ 2 / Fc ^ 2 * medium.rho * zetacst);
    dpstc = flowPort_st.p - flowPort_c.p;
    flowPort_c.H_flow = semiLinear(flowPort_c.m_flow, flowPort_c.h, h);
    flowPort_s.H_flow = semiLinear(flowPort_s.m_flow, flowPort_s.h, h);
    flowPort_st.H_flow = semiLinear(flowPort_st.m_flow, flowPort_st.h, h);

    annotation (
        Icon(
            coordinateSystem(initialScale = 0.1),
            graphics = {
                Polygon(
                    origin = {0, 30},
                    rotation = 180,
                    lineColor = {255, 0, 0},
                    fillColor = {0, 0, 255},
                    fillPattern = FillPattern.Solid,
                    points = {
                        {-90, 50}, 
                        {90, 50}, 
                        {90, 10}, 
                        {20, 10}, 
                        {20, -60}, 
                        {-20, -60}, 
                        {-20, 10}, 
                        {-90, 10}, 
                        {-90, 50}}), 
                Line(
                    points = {
                        {-52, 0}, 
                        {52, 0}},
                    thickness = 0.5,
                    arrow = {Arrow.Open, Arrow.None},
                    arrowSize = 10), 
                Line(
                    points = {
                        {0, 0}, 
                        {0, 52}},
                    thickness = 0.5), 
                Text(
                    origin = {-70, 0},
                    extent = {
                        {-30, 20}, 
                        {30, -20}},
                    textString = "C"), 
                Text(
                    origin = {70, 0},
                    extent = {
                        {-30, 20}, 
                        {30, -20}},
                    textString = "St"), 
                Text(
                    origin = {0, 70},
                    extent = {
                        {-30, 20}, 
                        {30, -20}},
                    textString = "S")}),
        Documentation(info = "<html>                           \n                <p>\n                    The component ConvergingTee is a specialized element that works only in a narrow boundary condition.\n                    It represents a 90° T-branch with equal diameter for main passage (sides c and st) and any diameter for branch s.\n                </p>\n                <p>\n                    The flow direction is mandantory and has to be from port st to port c and port s to port c.\n                    Other flow directions are not supported.\n                </p>\n                <p>\n                    Calculation of zeta is taken from Idelchik 'Handbook of Hydraulic Resistance', 4th Edition 2007, Diagram 7.4\n                </p>\n                </html>"));
end ConvergingTee;