Limiter

block Limiter "Limit the range of a signal"
    parameter Real uMax(start = 1) "Upper limits of input signals";
    parameter Real uMin = -uMax "Lower limits of input signals";
    parameter Boolean strict = false "= true, if strict limits with noEvent(..)"
        annotation (
            Evaluate = true,
            choices(checkBox = true),
            Dialog(tab = "Advanced"));
    parameter Types.LimiterHomotopy homotopyType = Modelica.Blocks.Types.LimiterHomotopy.Linear "Simplified model for homotopy-based initialization"
        annotation (
            Evaluate = true,
            Dialog(group = "Initialization"));
    parameter Boolean limitsAtInit = true "Has no longer an effect and is only kept for backwards compatibility (the implementation uses now the homotopy operator)"
        annotation (
            Dialog(tab = "Dummy"),
            Evaluate = true,
            choices(checkBox = true));

    extends Interfaces.SISO;

protected
    Real simplifiedExpr "Simplified expression for homotopy-based initialization";
equation
    if strict then 
        if homotopyType == Types.LimiterHomotopy.NoHomotopy then 
            y = smooth(0, noEvent(if uMax < u then uMax else if u < uMin then uMin else u));
        else 
            y = homotopy(actual = smooth(0, noEvent(if uMax < u then uMax else if u < uMin then uMin else u)), simplified = simplifiedExpr);
        end if;
    else 
        if homotopyType == Types.LimiterHomotopy.NoHomotopy then 
            y = smooth(0, if uMax < u then uMax else if u < uMin then uMin else u);
        else 
            y = homotopy(actual = smooth(0, if uMax < u then uMax else if u < uMin then uMin else u), simplified = simplifiedExpr);
        end if;
    end if;
    assert(uMin <= uMax, "Limiter: Limits must be consistent. However, uMax (=" + String(uMax) + ") < uMin (=" + String(uMin) + ")");
    simplifiedExpr = if homotopyType == Types.LimiterHomotopy.Linear then u else if homotopyType == Types.LimiterHomotopy.UpperLimit then uMax else if homotopyType == Types.LimiterHomotopy.LowerLimit then uMin else 0;

    annotation (
        Documentation(info = "<html>\n<p>\nThe Limiter block passes its input signal as output signal\nas long as the input is within the specified upper and lower\nlimits. If this is not the case, the corresponding limits are passed\nas output.\n</p>\n<p>\nThe parameter <code>homotopyType</code> in the Advanced tab specifies the\nsimplified behaviour if homotopy-based initialization is used:\n</p>\n<ul>\n<li><code>NoHomotopy</code>: the actual expression with limits is used</li>\n<li><code>Linear</code>: a linear behaviour y = u is assumed (default option)</li>\n<li><code>UpperLimit</code>: it is assumed that the output is stuck at the upper limit u = uMax</li>\n<li><code>LowerLimit</code>: it is assumed that the output is stuck at the lower limit u = uMin</li>\n</ul>\n<p>\nIf it is known a priori in which region the input signal will be located, this option can help\na lot by removing one strong nonlinearity from the initialization problem.\n</p>\n</html>"),
        Icon(
            coordinateSystem(
                preserveAspectRatio = true,
                extent = {
                    {-100, -100}, 
                    {100, 100}}),
            graphics = {
                Line(
                    points = {
                        {0, -90}, 
                        {0, 68}},
                    color = {192, 192, 192}), 
                Polygon(
                    points = {
                        {0, 90}, 
                        {-8, 68}, 
                        {8, 68}, 
                        {0, 90}},
                    lineColor = {192, 192, 192},
                    fillColor = {192, 192, 192},
                    fillPattern = FillPattern.Solid), 
                Line(
                    points = {
                        {-90, 0}, 
                        {68, 0}},
                    color = {192, 192, 192}), 
                Polygon(
                    points = {
                        {90, 0}, 
                        {68, -8}, 
                        {68, 8}, 
                        {90, 0}},
                    lineColor = {192, 192, 192},
                    fillColor = {192, 192, 192},
                    fillPattern = FillPattern.Solid), 
                Line(points = {
                    {-80, -70}, 
                    {-50, -70}, 
                    {50, 70}, 
                    {80, 70}}), 
                Text(
                    extent = {
                        {-150, -150}, 
                        {150, -110}},
                    textString = "uMax=%uMax"), 
                Line(
                    visible = strict,
                    points = {
                        {50, 70}, 
                        {80, 70}},
                    color = {255, 0, 0}), 
                Line(
                    visible = strict,
                    points = {
                        {-80, -70}, 
                        {-50, -70}},
                    color = {255, 0, 0})}),
        Diagram(
            coordinateSystem(
                preserveAspectRatio = true,
                extent = {
                    {-100, -100}, 
                    {100, 100}}),
            graphics = {
                Line(
                    points = {
                        {0, -60}, 
                        {0, 50}},
                    color = {192, 192, 192}), 
                Polygon(
                    points = {
                        {0, 60}, 
                        {-5, 50}, 
                        {5, 50}, 
                        {0, 60}},
                    lineColor = {192, 192, 192},
                    fillColor = {192, 192, 192},
                    fillPattern = FillPattern.Solid), 
                Line(
                    points = {
                        {-60, 0}, 
                        {50, 0}},
                    color = {192, 192, 192}), 
                Polygon(
                    points = {
                        {60, 0}, 
                        {50, -5}, 
                        {50, 5}, 
                        {60, 0}},
                    lineColor = {192, 192, 192},
                    fillColor = {192, 192, 192},
                    fillPattern = FillPattern.Solid), 
                Line(points = {
                    {-50, -40}, 
                    {-30, -40}, 
                    {30, 40}, 
                    {50, 40}}), 
                Text(
                    extent = {
                        {46, -6}, 
                        {68, -18}},
                    lineColor = {128, 128, 128},
                    textString = "u"), 
                Text(
                    extent = {
                        {-30, 70}, 
                        {-5, 50}},
                    lineColor = {128, 128, 128},
                    textString = "y"), 
                Text(
                    extent = {
                        {-58, -54}, 
                        {-28, -42}},
                    lineColor = {128, 128, 128},
                    textString = "uMin"), 
                Text(
                    extent = {
                        {26, 40}, 
                        {66, 56}},
                    lineColor = {128, 128, 128},
                    textString = "uMax")}));
end Limiter;