Valve

model Valve "Simple valve"
    extends Modelica.Thermal.FluidHeatFlow.Interfaces.Partials.TwoPort(m(start = 0), final tapT = 1);

    parameter Boolean LinearCharacteristic(start = true) "Type of characteristic"
        annotation (
            Dialog(group = "Standard characteristic"),
            choices(
                choice = true "Linear",
                choice = false "Exponential"));
    parameter Real y1(min = small, start = 1) "Max. valve opening"
        annotation (Dialog(group = "Standard characteristic"));
    parameter Modelica.SIunits.VolumeFlowRate Kv1(min = small, start = 1) "Max. flow @ y = y1"
        annotation (Dialog(group = "Standard characteristic"));
    parameter Real kv0(min = small, max = 1 - small, start = 0.01) "Leakage flow / max.flow @ y = 0"
        annotation (Dialog(group = "Standard characteristic"));
    parameter Modelica.SIunits.Pressure dp0(start = 1) "Standard pressure drop"
        annotation (Dialog(group = "Standard characteristic"));
    parameter Modelica.SIunits.Density rho0(start = 10) "Standard medium's density"
        annotation (Dialog(group = "Standard characteristic"));
    parameter Real frictionLoss(min = 0, max = 1, start = 0) "Part of friction losses fed to medium";
protected
    constant Modelica.SIunits.VolumeFlowRate unitVolumeFlowRate = 1;
    constant Real small = Modelica.Constants.small;
    constant Modelica.SIunits.VolumeFlowRate smallVolumeFlowRate = eps * unitVolumeFlowRate;
    constant Real eps = Modelica.Constants.eps;
    Real yLim = max(min(y, y1), 0) "Limited valve opening";
    Modelica.SIunits.VolumeFlowRate Kv "Standard flow rate";
public
    Modelica.Blocks.Interfaces.RealInput y annotation (Placement(transformation(
        extent = {
            {-20, -20}, 
            {20, 20}},
        rotation = 270,
        origin = {0, 100})));
initial algorithm
    assert(small < y1, "Valve characteristic: y1 has to be > 0 !");
    assert(smallVolumeFlowRate < Kv1, "Valve characteristic: Kv1 has to be > 0 !");
    assert(small < kv0, "Valve characteristic: kv0 has to be > 0 !");
    assert(kv0 < 1 - eps, "Valve characteristic: kv0 has to be < 1 !");
equation
    Kv / Kv1 = if LinearCharacteristic then kv0 + (1 - kv0) * yLim / y1 else kv0 * exp(Modelica.Math.log(kv0 ^ (-1)) * yLim / y1);
    dp / dp0 = medium.rho / rho0 * (V_flow / Kv) * abs(V_flow / Kv);
    Q_flow = frictionLoss * V_flow * dp;

    annotation (
        Documentation(info = "<html>\n<p>Simple controlled valve.</p>\n<p>\nStandard characteristic Kv=<em>f </em>(y) is given at standard conditions (dp0, rho0),\n</p>\n<ul>\n<li>either linear :<code> Kv/Kv1 = Kv0/Kv1 + (1-Kv0/Kv1) * y/Y1</code></li>\n<li>or exponential:<code> Kv/Kv1 = Kv0/Kv1 * exp[log(Kv1/Kv0) * y/Y1]</code></li>\n</ul>\n<p>\nwhere:\n</p>\n<ul>\n<li><code>Kv0 ... min. flow @ y = 0</code></li>\n<li><code>Y1 .... max. valve opening</code></li>\n<li><code>Kv1 ... max. flow @ y = Y1</code></li>\n</ul>\n<p>\nFlow resistance under real conditions is calculated by\n</p>\n<blockquote><pre>\nV_flow**2 * rho / dp = Kv(y)**2 * rho0 / dp0\n</pre></blockquote>\n</html>"),
        Icon(
            coordinateSystem(
                preserveAspectRatio = true,
                extent = {
                    {-100, -100}, 
                    {100, 100}}),
            graphics = {
                Polygon(
                    points = {
                        {-90, 10}, 
                        {-60, 10}, 
                        {-60, 60}, 
                        {0, 0}, 
                        {60, 60}, 
                        {60, 10}, 
                        {90, 10}, 
                        {90, -10}, 
                        {60, -10}, 
                        {60, -60}, 
                        {0, 0}, 
                        {-60, -60}, 
                        {-60, -10}, 
                        {-90, -10}, 
                        {-90, 10}},
                    lineColor = {255, 0, 0},
                    fillColor = {0, 0, 255},
                    fillPattern = FillPattern.Solid), 
                Line(
                    points = {
                        {0, 80}, 
                        {0, 0}},
                    color = {0, 0, 127}), 
                Text(
                    extent = {
                        {-150, -70}, 
                        {150, -110}},
                    textString = "%name",
                    lineColor = {0, 0, 255})}));
end Valve;