SimpleGenericOrifice

model SimpleGenericOrifice "Simple generic orifice defined by pressure loss coefficient and diameter (only for flow from port_a to port_b)"
    extends Modelica.Fluid.Interfaces.PartialTwoPortTransport(dp_start = dp_nominal, m_flow_small = if system.use_eps_Re then system.eps_m_flow * m_flow_nominal else system.m_flow_small, m_flow(stateSelect = if momentumDynamics == Types.Dynamics.SteadyState then StateSelect.default else StateSelect.prefer));
    extends Modelica.Fluid.Interfaces.PartialLumpedFlow(final pathLength = 0, final momentumDynamics = Types.Dynamics.SteadyState);

    parameter SI.Diameter diameter "Diameter of orifice";
    parameter Real zeta "Loss factor for flow of port_a -> port_b"
        annotation (Dialog(enable = use_zeta));
    parameter Boolean use_zeta = true "= false to obtain zeta from dp_nominal and m_flow_nominal";
    parameter SI.MassFlowRate m_flow_nominal = if system.use_eps_Re then system.m_flow_nominal else 100 * system.m_flow_small "Mass flow rate for dp_nominal"
        annotation (Dialog(group = "Nominal operating point"));
    parameter SI.Pressure dp_nominal = if not system.use_eps_Re then 1000 else BaseClasses.lossConstant_D_zeta(diameter, zeta) / Medium.density_pTX(Medium.p_default, Medium.T_default, Medium.X_default) * m_flow_nominal ^ 2 "Nominal pressure drop"
        annotation (Dialog(group = "Nominal operating point"));
    parameter Boolean use_Re = system.use_eps_Re "= true, if turbulent region is defined by Re, otherwise by m_flow_small"
        annotation (
            Dialog(tab = "Advanced"),
            Evaluate = true);
    parameter Boolean from_dp = true "= true, use m_flow = f(dp) else dp = f(m_flow)"
        annotation (
            Evaluate = true,
            Dialog(tab = "Advanced"));
protected
    parameter Medium.AbsolutePressure dp_small(min = 0) = if system.use_eps_Re then dp_nominal / m_flow_nominal * m_flow_small else system.dp_small "Regularization of zero flow if |dp| < dp_small"
        annotation (Dialog(
            tab = "Advanced",
            enable = not use_Re and from_dp));
public
    Real zeta_nominal;
    Medium.Density d = 0.5 * (Medium.density(state_a) + Medium.density(state_b));
    Modelica.SIunits.Pressure dp_fg(start = dp_start) "pressure loss due to friction and gravity";
    Modelica.SIunits.Area A_mean = 0.25 * Modelica.Constants.pi * diameter ^ 2 "mean cross flow area";
    constant SI.ReynoldsNumber Re_turbulent = 10000 "cf. sharpEdgedOrifice";
    SI.MassFlowRate m_flow_turbulent = if not use_Re then m_flow_small else max(m_flow_small, 0.125 * Modelica.Constants.pi * diameter * (Medium.dynamicViscosity(state_a) + Medium.dynamicViscosity(state_b)) * Re_turbulent);
    SI.AbsolutePressure dp_turbulent = if not use_Re then dp_small else max(dp_small, BaseClasses.lossConstant_D_zeta(diameter, zeta_nominal) / d * m_flow_turbulent ^ 2);
equation
    if from_dp then 
        m_flow = homotopy(Utilities.regRoot2(dp_fg, dp_turbulent, Medium.density(state_a) / BaseClasses.lossConstant_D_zeta(diameter, zeta_nominal), Medium.density(state_b) / BaseClasses.lossConstant_D_zeta(diameter, zeta_nominal)), m_flow_nominal * dp_fg / dp_nominal);
    else 
        dp_fg = homotopy(Utilities.regSquare2(m_flow, m_flow_turbulent, BaseClasses.lossConstant_D_zeta(diameter, zeta_nominal) / Medium.density(state_a), BaseClasses.lossConstant_D_zeta(diameter, zeta_nominal) / Medium.density(state_b)), dp_nominal * m_flow / m_flow_nominal);
    end if;
    if use_zeta then 
        zeta_nominal = zeta;
    else 
        zeta_nominal = 2 * A_mean ^ 2 * d * dp_nominal / m_flow_nominal ^ 2;
    end if;
    F_fg = A_mean * dp_fg;
    F_p = A_mean * (Medium.pressure(state_b) - Medium.pressure(state_a));
    Ib_flow = 0;
    port_a.h_outflow = inStream(port_b.h_outflow);
    port_b.h_outflow = inStream(port_a.h_outflow);

    annotation (
        defaultComponentName = "orifice",
        Icon(
            coordinateSystem(
                preserveAspectRatio = false,
                extent = {
                    {-100, -100}, 
                    {100, 100}}),
            graphics = {
                Line(
                    points = {
                        {-60, -50}, 
                        {-60, 50}, 
                        {60, -50}, 
                        {60, 50}},
                    thickness = 0.5), 
                Line(
                    points = {
                        {-60, 0}, 
                        {-100, 0}},
                    color = {0, 127, 255}), 
                Line(
                    points = {
                        {60, 0}, 
                        {100, 0}},
                    color = {0, 127, 255}), 
                Text(
                    extent = {
                        {-173, 104}, 
                        {175, 62}},
                    textString = "zeta=%zeta")}),
        Documentation(info = "<html>\n<p>\nThis pressure drop component defines a\nsimple, generic orifice, where the loss factor &zeta; is provided\nfor one flow direction (e.g., from loss table of a book):\n</p>\n\n<pre>   &Delta;p = 0.5*&zeta;*&rho;*v*|v|\n      = 8*&zeta;/(&pi;^2*D^4*&rho;) * m_flow*|m_flow|\n</pre>\n\n<p>\nwhere\n</p>\n<ul>\n<li> &Delta;p is the pressure drop: &Delta;p = port_a.p - port_b.p</li>\n<li> D is the diameter of the orifice at the position where\n     &zeta; is defined (either at port_a or port_b). If the orifice has not a\n     circular cross section, D = 4*A/P, where A is the cross section\n     area and P is the wetted perimeter.</li>\n<li> &zeta; is the loss factor with respect to D\n     that depends on the geometry of\n     the orifice. In the turbulent flow regime, it is assumed that\n     &zeta; is constant.<br>\n     For small mass flow rates, the flow is laminar and is approximated\n     by a polynomial that has a finite derivative for m_flow=0.</li>\n<li> v is the mean velocity.</li>\n<li> &rho; is the upstream density.</li>\n</ul>\n\n<p>\nSince the pressure loss factor zeta is provided only for a mass flow\nfrom port_a to port_b, the pressure loss is not correct when the\nflow is reversing. If reversing flow only occurs in a short time interval,\nthis is most likely uncritical. If significant reversing flow\ncan appear, this component should not be used.\n</p>\n</html>"));
end SimpleGenericOrifice;