CriticalDamping

block CriticalDamping "Output the input signal filtered with an n-th order filter with critical damping"
    import Modelica.Blocks.Types.Init;

    extends Modelica.Blocks.Interfaces.SISO;

    parameter Integer n = 2 "Order of filter";
    parameter Modelica.SIunits.Frequency f(start = 1) "Cut-off frequency";
    parameter Boolean normalized = true "= true, if amplitude at f_cut is 3 dB, otherwise unmodified filter";
    parameter Modelica.Blocks.Types.Init initType = Modelica.Blocks.Types.Init.NoInit "Type of initialization (1: no init, 2: steady state, 3: initial state, 4: initial output)"
        annotation (
            Evaluate = true,
            Dialog(group = "Initialization"));
    parameter Real x_start[n] = zeros(n) "Initial or guess values of states"
        annotation (Dialog(group = "Initialization"));
    parameter Real y_start = 0 "Initial value of output (remaining states are in steady state)"
        annotation (Dialog(
            enable = initType == Init.InitialOutput,
            group = "Initialization"));
    output Real x[n](start = x_start) "Filter states";
protected
    parameter Real alpha = if normalized then sqrt(2 ^ (n ^ (-1)) - 1) else 1 "Frequency correction factor for normalized filter";
    parameter Real w = 2 * Modelica.Constants.pi * f / alpha;
initial equation
    if initType == Init.SteadyState then 
        der(x) = zeros(n);
    elseif initType == Init.InitialState then 
        x = x_start;
    elseif initType == Init.InitialOutput then 
        y = y_start;
        der(x[1:n - 1]) = zeros(n - 1);
    end if;
equation
    for i in 2:n loop
        der(x[i]) = (x[i - 1] - x[i]) * w;
    end for;
    y = x[n];
    der(x[1]) = (u - x[1]) * w;

    annotation (
        Icon(
            coordinateSystem(
                preserveAspectRatio = true,
                extent = {
                    {-100, -100}, 
                    {100, 100}}),
            graphics = {
                Line(
                    points = {
                        {-80.6897, 77.6256}, 
                        {-80.6897, -90.3744}},
                    color = {192, 192, 192}), 
                Polygon(
                    lineColor = {192, 192, 192},
                    fillColor = {192, 192, 192},
                    fillPattern = FillPattern.Solid,
                    points = {
                        {-79.7044, 90.6305}, 
                        {-87.7044, 68.6305}, 
                        {-71.7044, 68.6305}, 
                        {-79.7044, 90.6305}}), 
                Line(
                    points = {
                        {-90, -80}, 
                        {82, -80}},
                    color = {192, 192, 192}), 
                Polygon(
                    lineColor = {192, 192, 192},
                    fillColor = {192, 192, 192},
                    fillPattern = FillPattern.Solid,
                    points = {
                        {90, -80}, 
                        {68, -72}, 
                        {68, -88}, 
                        {90, -80}}), 
                Text(
                    lineColor = {192, 192, 192},
                    extent = {
                        {0, -60}, 
                        {60, 0}},
                    textString = "PTn"), 
                Line(
                    origin = {-17.976, -6.521},
                    points = {
                        {96.962, 55.158}, 
                        {16.42, 50.489}, 
                        {-18.988, 18.583}, 
                        {-32.024, -53.479}, 
                        {-62.024, -73.479}},
                    color = {0, 0, 127},
                    smooth = Smooth.Bezier), 
                Text(
                    lineColor = {192, 192, 192},
                    extent = {
                        {-70, 48}, 
                        {26, 94}},
                    textString = "%n"), 
                Text(
                    extent = {
                        {8, -146}, 
                        {8, -106}},
                    textString = "f=%f")}),
        Diagram(
            coordinateSystem(
                preserveAspectRatio = true,
                extent = {
                    {-100, -100}, 
                    {100, 100}}),
            graphics = {
                Line(points = {
                    {40, 0}, 
                    {-40, 0}}), 
                Text(
                    extent = {
                        {-55, 55}, 
                        {55, 5}},
                    textString = "1"), 
                Rectangle(
                    extent = {
                        {-60, 60}, 
                        {60, -60}},
                    lineColor = {0, 0, 255}), 
                Line(
                    points = {
                        {-100, 0}, 
                        {-60, 0}},
                    color = {0, 0, 255}), 
                Line(
                    points = {
                        {60, 0}, 
                        {100, 0}},
                    color = {0, 0, 255}), 
                Text(
                    extent = {
                        {-54, -6}, 
                        {44, -56}},
                    textString = "(s/w + 1)"), 
                Text(
                    extent = {
                        {38, -10}, 
                        {58, -30}},
                    textString = "n")}),
        Documentation(info = "<html>\n<p>This block defines the transfer function between the\ninput u and the output y\nas an n-th order filter with <em>critical damping</em>\ncharacteristics and cut-off frequency f. It is\nimplemented as a series of first order filters.\nThis filter type is especially useful to filter the input of an\ninverse model, since the filter does not introduce any transients.\n</p>\n\n<p>\nIf parameter <strong>normalized</strong> = <strong>true</strong> (default), the filter\nis normalized such that the amplitude of the filter transfer function\nat the cut-off frequency f is 1/sqrt(2) (= 3 dB). Otherwise, the filter\nis not normalized, i.e., it is unmodified. A normalized filter is usually\nmuch better for applications, since filters of different orders are\n\"comparable\", whereas non-normalized filters usually require to adapt the\ncut-off frequency, when the order of the filter is changed.\nFigures of the filter step responses are shown below.\nNote, in versions before version 3.0 of the Modelica Standard library,\nthe CriticalDamping filter was provided only in non-normalized form.\n</p>\n\n<p>If transients at the simulation start shall be avoided, the filter\nshould be initialized in steady state (e.g., using option\ninitType=Modelica.Blocks.Types.Init.SteadyState).\n</p>\n\n<p>\nThe critical damping filter is defined as\n</p>\n\n<pre>\n    &alpha; = <strong>if</strong> normalized <strong>then</strong> <strong>sqrt</strong>(2^(1/n) - 1) <strong>else</strong> 1 // frequency correction factor\n    &omega; = 2*&pi;*f/&alpha;\n              1\n    y = ------------- * u\n         (s/w + 1)^n\n\n</pre>\n\n<p>\n<img src=\"modelica://Modelica/Resources/Images/Blocks/CriticalDampingNormalized.png\"\n     alt=\"CriticalDampingNormalized.png\">\n</p>\n\n<p>\n<img src=\"modelica://Modelica/Resources/Images/Blocks/CriticalDampingNonNormalized.png\"\n     alt=\"CriticalDampingNonNormalized.png\">\n</p>\n\n</html>"));
end CriticalDamping;