## Modelica_LinearSystems2.TransferFunction.Conversion

### Package Content

Name | Description
--- | ---
toZerosAndPoles | Generate a ZerosAndPoles object from a TransferFunction object
toStateSpace | Convert a TransferFunction into a StateSpace representation
toZerosAndPolesMIMO | Generate a zeros-and-poles transfer function matrix from a numerator-denominator-polynomial transfer function matrix representation
toMatrices | Convert a TransferFunction into the matrices A, B, C of a StateSpace

## Modelica_LinearSystems2.TransferFunction.Conversion.toZerosAndPoles

Generate a ZerosAndPoles object from a TransferFunction object

### Information

#### Syntax

zp | = | TransferFunction.Conversion.toZerosAndPoles(tf)

#### Description

Computes a ZerosAndPoles record

>                      product(s + n1[i]) * product(s^2 + n2[i,1]*s + n2[i,2])
>             zp = k*---------------------------------------------------------
>                     product(s + d1[i]) * product(s^2 + d2[i,1]*s + d2[i,2])

of a transfer function representated by numerator and denominator polynomial. The poles and zeros and the gain `k` are computed (zerosAndPoles) and are used as inputs the ZerosAndPoles constructor.

#### Example

>        TransferFunction s = Modelica_LinearSystems2.TransferFunction.s();
>        Modelica_LinearSystems2.TransferFunction tf = 1/(s^2 + 3*s +2)

>     algorithm
>       zp:=Modelica_LinearSystems2.TransferFunction.Conversion.toZerosAndPoles(tf);
>     //  zp = 1/( (s + 1)*(s + 2) )

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
TransferFunction | tf |  | transfer function of a system

### Outputs

Type | Name | Description
--- | --- | ---
ZerosAndPoles | zp |

### Modelica definition

    encapsulated function toZerosAndPoles
      "Generate a ZerosAndPoles object from a TransferFunction object"
      import Modelica;
      import Modelica_LinearSystems2.ZerosAndPoles;
      import Modelica_LinearSystems2.ZerosAndPoles.Internal;
      import Modelica_LinearSystems2.TransferFunction;
      import Modelica_LinearSystems2.Math.Complex;

      input TransferFunction tf "transfer function of a system";
      output ZerosAndPoles zp(
        redeclare Real n1[Internal.numberOfRealZeros2(tf)],
        redeclare Real n2[integer((size(tf.n, 1) - 1 -
          Internal.numberOfRealZeros2(tf))/2),2],
        redeclare Real d1[Internal.numberOfRealPoles(tf)],
        redeclare Real d2[integer((size(tf.d, 1) - 1 -
          Internal.numberOfRealPoles(tf))/2),2]);
    protected
      Complex z[:];
      Complex p[:];
      Real k;
    algorithm
      (z,p,k) := TransferFunction.Analysis.zerosAndPoles(tf);
      zp := ZerosAndPoles(
          z,
          p,
          k);
    end toZerosAndPoles;

## Modelica_LinearSystems2.TransferFunction.Conversion.toStateSpace

Convert a TransferFunction into a StateSpace representation

### Information

#### Syntax

ss | = | TransferFunction.Conversion.toStateSpacetoStateSpace(tf)

#### Description

Transforms a transfer function into state space representation. There are an infinite number of possible realizations. Here, the transfer function is transformed into controller canonical form, i.e. the transfer function

>            b4*s^4 + b3*s^3 + b2*s^2 + b1*s + b0
>       y = -------------------------------------- *u
>            a4*s^4 + a3*s^3 + a2*s^2 + a1*s + a0

is transformed into:

>       der(x) = A*x + B*u;
>           y  = C*x + D*u;
>          with
>                  A = [   0  ,    1  ,    0  ,    0;
>                          0  ,    0  ,    1  ,    0:
>                          0  ,    0  ,    0  ,    1;
>                       -a0/a4, -a1/a4, -a2/a4, -a3/a4];

>                  B = [  0;
>                         0;
>                         0;
>                        1/a4];
>                  C = [b0-b4*a0/a4, b1-b4*a1/a4, b2-b4*a2/a4, b3-b4*a3/a4];
>                  D = [b4/a4];

If the numerator polynomial is 1, then the state vector x is built up of y and of all derivatives of y upto nx-1 (nx is the dimension of the state vector):

>        x = {y, dy/dt, d^2y/dt^2, ..., d^(n-1)y/dt^(n-1)};

Note, the state vector x of Modelica.Blocks.Continuous.TransferFunction is defined slightly differently.

#### Example

>        TransferFunction s = Modelica_LinearSystems2.TransferFunction.s();
>        Modelica_LinearSystems2.TransferFunction tf=(s+1)/(s^3 + s^2 + s +1);

>     algorithm
>       ss := Modelica_LinearSystems2.TransferFunction.Conversion.toStateSpace(tf);
>     // ss.A = [0, 1, 0; 0, 0, 1; -1, -1, -1],
>     // ss.B = [0; 0; 1],
>     // ss.C = [1, 1, 0],
>     // ss.D = [0],

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
TransferFunction | tf |  | transfer function of a system

### Outputs

Type | Name | Description
--- | --- | ---
StateSpace | ss | Transfer function in StateSpace form

### Modelica definition

    function toStateSpace
      "Convert a TransferFunction into a StateSpace representation"
      import Modelica;
      import Modelica_LinearSystems2;
      import Modelica_LinearSystems2.TransferFunction;
      import Modelica.Math.Vectors;

     input Modelica_LinearSystems2.TransferFunction tf
        "transfer function of a system";
          output Modelica_LinearSystems2.StateSpace ss(
            redeclare Real A[TransferFunction.Analysis.denominatorDegree(tf),TransferFunction.Analysis.denominatorDegree(tf)],
            redeclare Real B[TransferFunction.Analysis.denominatorDegree(tf),1],
            redeclare Real C[1,TransferFunction.Analysis.denominatorDegree(tf)],
            redeclare Real D[1,1]) "Transfer function in StateSpace form";

    protected
     Integer na=TransferFunction.Analysis.denominatorDegree(tf) + 1;
     Integer nb=TransferFunction.Analysis.numeratorDegree(tf) + 1;
     Integer nx=na - 1;
     Real a[na]=Vectors.reverse(tf.d) "Reverse element order of tf.a";
     Real b[na]=vector([Vectors.reverse(tf.n); zeros(na - nb, 1)]);
     Real d=b[na]/a[na];
    algorithm
     if nx == 0 then
       ss.A := fill(
           0,
           0,
           nx);
       ss.B := fill(
           0,
           0,
           1);
       ss.C := fill(
           0,
           1,
           0);
     else
       ss.A[1:nx - 1, 1:nx] := [zeros(nx - 1, 1),identity(nx - 1)];
       ss.A[nx, 1:nx] := -a[1:na - 1]/a[na];
       ss.B := [zeros(nx - 1, 1); 1/a[na]];
       ss.C := {b[1:nx] - d*a[1:nx]};

    end if;

      ss.D := [d];
    end toStateSpace;

## Modelica_LinearSystems2.TransferFunction.Conversion.toZerosAndPolesMIMO

Generate a zeros-and-poles transfer function matrix from a numerator-denominator-polynomial transfer function matrix representation

### Information

#### Syntax

zp | = | TransferFunction.Conversion.toZerosAndPolesMIMO(tf)

#### Description

Converts a matrix of transfer functions denoted as rational polynomial function into a matrix of transfer functions in zeros-and-poles representation. The function repetitively uses toZerosAndPoles.

#### Example

>        TransferFunction s = Modelica_LinearSystems2.TransferFunction.s();
>        Modelica_LinearSystems2.TransferFunction tf = [1/(s^2 + 3*s +2);s/(s^2 + 2*s +1)]

>     algorithm
>       zp:=Modelica_LinearSystems2.TransferFunction.Conversion.toZerosAndPoles(tf);
>     //  zp = [1/( (s + 1)*(s + 2) ); s/( (s + 1)^2 )]

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
TransferFunction | tf[:, :] |  | transfer function of a system

### Outputs

Type | Name | Description
--- | --- | ---
ZerosAndPoles | zp[size(tf, 1), size(tf, 2)] |

### Modelica definition

    encapsulated function toZerosAndPolesMIMO
      "Generate a zeros-and-poles transfer function matrix from a numerator-denominator-polynomial transfer function matrix representation"

        import Modelica;
        import Modelica_LinearSystems2;
        import Modelica_LinearSystems2.ZerosAndPoles;
        import Modelica_LinearSystems2.TransferFunction;

      input TransferFunction tf[:,:] "transfer function of a system";

      output ZerosAndPoles zp[size(tf, 1),size(tf, 2)];

    protected
      Integer ny=size(tf, 1);
      Integer nu=size(tf, 2);

    algorithm
      for iy in 1:ny loop
        for iu in 1:nu loop
          zp[iy, iu] := ZerosAndPoles(tf[iy, iu]);
        end for;
      end for;
    end toZerosAndPolesMIMO;

## Modelica_LinearSystems2.TransferFunction.Conversion.toMatrices

Convert a TransferFunction into the matrices A, B, C of a StateSpace

### Information

#### Syntax

(A, B, C, D) | = | TransferFunction.Conversion.toStateSpacetoStateSpace(tf)

#### Description

Transforms a transfer function into state space representation. The outputs are the system functions A, B, C, D. There are an infinite number of possible realizations. Here, the transfer function is transformed into controller canonical form, i.e. the transfer function

>            b4*s^4 + b3*s^3 + b2*s^2 + b1*s + b0
>       y = -------------------------------------- *u
>            a4*s^4 + a3*s^3 + a2*s^2 + a1*s + a0

is transformed into:

>       der(x) = A*x + B*u;
>           y  = C*x + D*u;
>          with
>                  A = [   0  ,    1  ,    0  ,    0;
>                          0  ,    0  ,    1  ,    0:
>                          0  ,    0  ,    0  ,    1;
>                       -a0/a4, -a1/a4, -a2/a4, -a3/a4];

>                  B = [  0;
>                         0;
>                         0;
>                        1/a4];
>                  C = [b0-b4*a0/a4, b1-b4*a1/a4, b2-b4*a2/a4, b3-b4*a3/a4];
>                  D = [b4/a4];

If the numerator polynomial is 1, then the state vector x is built up of y and of all derivatives of y upto nx-1 (nx is the dimension of the state vector):

>        x = {y, dy/dt, d^2y/dt^2, ..., d^(n-1)y/dt^(n-1)};

Note, the state vector x of Modelica.Blocks.Continuous.TransferFunction is defined slightly differently.

#### Example

>        TransferFunction s = Modelica_LinearSystems2.TransferFunction.s();
>        Modelica_LinearSystems2.TransferFunction tf=(s+1)/(s^3 + s^2 + s +1);

>     algorithm
>       (A, B, C, D) := Modelica_LinearSystems2.TransferFunction.Conversion.toStateSpace(tf);
>     // A = [0, 1, 0; 0, 0, 1; -1, -1, -1],
>     // B = [0; 0; 1],
>     // C = [1, 1, 0],
>     // D = [0],

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
TransferFunction | tf |  | transfer function of a system

### Outputs

Type | Name | Description
--- | --- | ---
Real | ABCD[size(tf.d, 1), size(tf.d, 1)] |

### Modelica definition

    function toMatrices
      "Convert a TransferFunction into the matrices A, B, C of a StateSpace"

      import Modelica;
      import Modelica_LinearSystems2;
      import Modelica_LinearSystems2.TransferFunction;
      import Modelica.Math.Vectors;

     input Modelica_LinearSystems2.TransferFunction tf
        "transfer function of a system";

          output Real ABCD[size(tf.d,1),size(tf.d,1)];

    protected
     Integer na=TransferFunction.Analysis.denominatorDegree(tf) + 1;
     Integer nb=TransferFunction.Analysis.numeratorDegree(tf) + 1;
     Integer nx=na - 1;
     output Real A[nx,nx];
     output Real B[nx,1];
     output Real C[1,nx];
     output Real D[1,1];
     Real a[na]=Vectors.reverse(tf.d) "Reverse element order of tf.a";
     Real b[na]=vector([Vectors.reverse(tf.n); zeros(na - nb, 1)]);
     Real d=b[na]/a[na];
    algorithm
     if nx == 0 then
       A := fill(
           0,
           0,
           nx);
       B := fill(
           0,
           0,
           1);
       C := fill(
           0,
           1,
           0);
     else
       A[1:nx - 1, 1:nx] := [zeros(nx - 1, 1),identity(nx - 1)];
       A[nx, 1:nx] := -a[1:na - 1]/a[na];
       B := [zeros(nx - 1, 1); 1/a[na]];
       C := {b[1:nx] - d*a[1:nx]};
    end if;
      D := [d];
      ABCD := [A,B;C,D];
    end toMatrices;

## Modelica_LinearSystems2.ZerosAndPoles.Conversion

### Package Content

Name | Description
--- | ---
toTransferFunction | Generate a TransferFunction object from a ZerosAndPoles object
toTransferFunctionMIMO | Generate a transfer function matrix from zeros-and-poles transfer function matrix
toStateSpace | Transform a ZerosAndPoles object into a StateSpace object
toMatrices | Convert a ZerosAndPoles object into the matrices A, B, C of a StateSpace

## Modelica_LinearSystems2.ZerosAndPoles.Conversion.toTransferFunction

Generate a TransferFunction object from a ZerosAndPoles object

### Information

#### Syntax

tf | = | ZerosAndPoles.Conversion.toTransferFunction(zp)

#### Description

Computes a TransferFunction record

>                n(s)     b0 + b1*s + ... + bn*s^n
>        tf = -------- = --------------------------
>                d(s)     a0 + a1*s + ... + an*s^n

from a ZerosAndPoles record representated by first and second order numerator and denominator polynomials. The poles and zeros and the gain `k` are computed (zerosAndPoles) and are used as inputs in the TransferFunction constructor.

#### Example

>        ZerosAndPoles p = Modelica_LinearSystems2.ZerosAndPoles.p();
>        Modelica_LinearSystems2.ZerosAndPoles tf = 1/(p + 3)/(p + 1)

>     algorithm
>       zp:=Modelica_LinearSystems2.ZerosAndPoles.Conversion.toTransferFunction(tf);
>     //  zp = 1/( (p + 1)*(p + 2) )

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
ZerosAndPoles | zp |  | ZerosAndPoles transfer function of a system

### Outputs

Type | Name | Description
--- | --- | ---
TransferFunction | tf |

### Modelica definition

    function toTransferFunction
      "Generate a TransferFunction object from a ZerosAndPoles object"
      //encapsulated function fromZerosAndPoles
      import Modelica;
      import Modelica_LinearSystems2.Math.Polynomial;
      import Modelica_LinearSystems2.TransferFunction;
      import Modelica_LinearSystems2.ZerosAndPoles;
      import Modelica_LinearSystems2.Internal;
      import Modelica_LinearSystems2.Math.Complex;

      input ZerosAndPoles zp "ZerosAndPoles transfer function of a system";
      output TransferFunction tf;

    protected
      Real k;
      Complex z[:];
      Complex p[:];
      Polynomial pn;
      Polynomial pd;
    algorithm
      (z,p,k) := ZerosAndPoles.Analysis.zerosAndPoles(zp);
      pn := Polynomial(z)*Polynomial(k);
      pd := Polynomial(p);
      tf.n := pn.c;
      tf.d := pd.c;
      tf.uName := zp.uName;
      tf.yName := zp.yName;
    end toTransferFunction;

## Modelica_LinearSystems2.ZerosAndPoles.Conversion.toTransferFunctionMIMO

Generate a transfer function matrix from zeros-and-poles transfer function matrix

### Information

#### Syntax

tf | = | TransferFunction.Conversion.toTransferFunctionMIMO(tf)

#### Description

Converts a matrix of ZerosAndPoles transfer functions denoted by the product of first and second order numerator and denominator polynomials into a matrix of transfer functions represented by (usual) numerator and denominator polynomial. The function repetitively uses toTransferFunction.

#### Example

>        ZerosAndPoles p = Modelica_LinearSystems2.ZerosAndPoles.p();
>        Modelica_LinearSystems2.ZerosAndPoles zp = [1/(p + 2)/(p + 1);p/(p + 1)/(p + 1)]

>     algorithm
>       tf := Modelica_LinearSystems2.ZerosAndPoles.Conversion.toTransferFunction(zp);
>     //  tf = [1/( (p + 1)*(p + 2) ); p/( (p + 1)^2 )]

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
ZerosAndPoles | zp[:, :] |  | ZerosAndPoles transfer function of a system

### Outputs

Type | Name | Description
--- | --- | ---
TransferFunction | tf[size(zp, 1), size(zp, 2)] |

### Modelica definition

    encapsulated function toTransferFunctionMIMO
      "Generate a transfer function matrix  from zeros-and-poles transfer function matrix"

        import Modelica;
        import Modelica_LinearSystems2;
        import Modelica_LinearSystems2.ZerosAndPoles;
        import Modelica_LinearSystems2.TransferFunction;

      input ZerosAndPoles zp[:,:] "ZerosAndPoles transfer function of a system";

      output TransferFunction tf[size(zp, 1),size(zp, 2)];

    protected
      Integer ny=size(zp, 1);
      Integer nu=size(zp, 2);

    algorithm
      for iy in 1:ny loop
        for iu in 1:nu loop
          tf[iy, iu] := ZerosAndPoles.Conversion.toTransferFunction(zp[iy, iu]);
        end for;
      end for;
    end toTransferFunctionMIMO;

## Modelica_LinearSystems2.ZerosAndPoles.Conversion.toStateSpace

Transform a ZerosAndPoles object into a StateSpace object

### Information

#### Syntax

ss | = | ZerosAndPoles.Conversion.toStateSpacetoStateSpace(tf)

#### Description

This function transforms a zeros-poles-gain system representation into state space representation. To achieve well numerical condition the ZerosAndPoles transfer function is transformed into state space form by creating first and second order blocks that are connected together in series. Every block is represented in controller canonical form and scaled such that the gain from the input of this block to its output is one (i.e. y(p=0) = u(p=0)), if this is possible. Details are given below.

Algorithmic details

The ZerosAndPoles transfer function is defined as:

>              product(p + n1[i]) * product(p^2 + n2[i,1]*p + n2[i,2])
>       y = k*--------------------------------------------------------- * u
>              product(p + d1[i]) * product(p^2 + d2[i,1]*p + d2[i,2])

This is treated as a series connection of first and second order systems. If size(n1) == size(d1) and size(n2) == size(d2) this gives the following sequence of operations:

>             p^2 + n2[1,1]*p + n2[1,2]
>       y_1 = ------------------------- * u
>             p^2 + d2[1,1]*p + d2[1,2]

>             p^2 + n2[2,1]*p + n2[2,2]
>       y_2 = ------------------------- * y_1
>             p^2 + d2[2,1]*p + d2[2,2]

>          ...

>             p + n1[..]
>       y_n = ---------- * y_(n-1)
>             p + d1[..]

>         y = k*y_n

Based on this representation, evrey block with transfer function G(p) could be transformed into

>       G(p) = k * F(p)

> with F(p) has unit gain. This leads to representations of the forms

>                a2 + a1*p + p^2       a2      b2 + a1*b2/a2*p + b2/a2*p^2
>       G(p) = -------------------- = ---- * ------------------------------ = k * F(p),  k = a2/b2  (1)

>                b2 + b1*p + p^2       b2           b2 + b1*p + p^2

>     for second order systems and

>                a + p     a     b + b/a*p
>       G(p) = -------- = --- * ---------- = k * F(p),   k = a/b

>                b + p     b      b + p

for first order systems respectively.

The complete system is now considered as the series connections of all the single unit gain transfer functions and an overall gain k with

>       k = product(ki).

In the general case, the following system structures and the corresponding state space systems can appear (note, 'c' is the reciprocal local gain 1/k):

>     (1)
>               a2 + a1*p + p^2           der(x1) = x2
>         y = ---------------------  -->  der(x2) = -b2*x1 - b1*x2 + b2*u
>               b2 + b1*p + p^2                 y = c*((a2-b2)*x1 + (a1-b1)*x2 + u),  c = b2/a2

>     (2)
>                  p + a                 der(x1) = x2
>         y = ---------------- * u  -->  der(x2) = -b2*x1 - b1*x2 + b2*u
>             b2 + b1*p + p^2                  y = k*(a1/b2*x1 +x2/b2),  c = b2/a

>     (3)
>                    1                  der(x1) = x2
>         y = --------------- *u   -->  der(x2) = -b2*x1 - b1*x2 + b2*u
>             b2 + b1*p + p^2                 y = c*x1/b2,  c = b2

>     (4)
>            a + p                       der(x) = -b*x + b*u
>        y = ----- * u             -->        y = c*((a-b)/b*x + u),  c = b/a
>            b + p

>     (5)
>              1
>        y = ----- * u             -->   der(x) = -b*x + b*u
>            b + p                            y = x,  c = b

If the sizes of the numerator and denominator polynomials do not match, the small systems are built in the following way:

>     (1) Build systems of form (1) by combining
>         - 1 d2 and 1 n2
>           (= 1 second order denominator and 1 second order numerator) or
>         - 1 d2 and 2 n1 or
>         - 2 d1 and 1 n2
>     (2) Build at most one system of form (2) by combining
>         - 1 d2 and 1 n2
>     (3) Build systems of form (3) by
>         - 1 d2
>     (4) Build systems of form (4) by combining
>         - 1 d1 and 1 n1
>     (5) Build systems of form (5) by
>         - 1 d1

The numeric properties of the resulting state space system depends on which first and second order polynomials are combined and connected together. From a numerical point of view, it would therefore be useful to combine the polynomials based on the numeric values of the polynomial coefficients, (e.g., in a first step the polynomials could be sorted according to their cut-off frequency).

However, this has the disadvantage that the structure of the resulting state space system depends on the numeric values of the polynomial coefficients. Since Modelica environments perform symbolic pre-processing on equations, this would mean that a change of a polynomial coefficient requires to newly compile the state space system.

If, on the other hand, the structure of the state space system depends only on dimension information of the n1,n2,d1,d2 arrays, then the polynomial coefficients can be changed without a new translation of the model. This is the major reason why the structure of the state space system in the implementation of this block is based only on dimension information.

This is, e.g., not critical for the provided filters: The dimension of the n1,n2,d1,d2 arrays depend for filters only on the filter characteristics (Bessel, Butterworth etc.), the filter type (low pass, high pass etc.) and on the filter order. If any of this data is changed, the model has to be newly compiled. All the other filter data, such as cut-off frequency or ripple amplitude, can be changed without re-compilation of the model. The ZerosAndPoles transfer function is now constructed for the filters in such a way that the filter zeros and poles are appropriately sorted to give better numerical properties.

Another alternative implementation of the state space system would be to use the function controller canonical form that directly results from the transfer function. The severe disadvantage of this approach is that the structure of the state space system from above is lost for the symbolic preprocessing. If, e.g., index reduction has to be applied (e.g. since a filter is used to realize a non-linear inverse model), then the tool cannot perform the index reduction. Example:

Assume, a generic first order state space system is present

>        der(x) = a*x + b*u
>             y = c*x + d*u

and the values of the scalars a,b,c,d are parameters that might be changed before the simulation starts. If y has to be differentiated symbolically during code generation, then

>           der(y) = c*der(x) + d*der(u)
>           der(x) = a*x + b*u

As a result, u needs to be differentiated too, and this might not be possible and therefore translation might fail.

On the other hand, if the first order system is defined to be a low pass filter and the state space system is generated by keeping this structure, we have (see form (5) above):

>       der(x) = -b*x + u
>             y = x

Differentiating y symbolically leads to:

>          der(y) = der(x)
>          der(x) = -b*x + u

Therefore, in this case, the derivative of u is not needed and the tool can continue with the symbolic processing.

#### Example

>        ZerosAndPoles p = Modelica_LinearSystems2.ZerosAndPoles.p();
>        Modelica_LinearSystems2.ZerosAndPoles zp=(p+1)/(p^2 + p +1);

>     algorithm
>       ss := Modelica_LinearSystems2.ZerosAndPoles.Conversion.toStateSpace(zp);
>     // ss.A = [0, 1; -1, -1],
>     // ss.B = [0; 1],
>     // ss.C = [1, 1],
>     // ss.D = [0],

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
ZerosAndPoles | zp |  | ZerosAndPoles transfer function of a system

### Outputs

Type | Name | Description
--- | --- | ---
StateSpace | ss | Transfer function in StateSpace SISO form

### Modelica definition

    function toStateSpace
      "Transform a ZerosAndPoles object into a StateSpace object"
     //encapsulated function fromZerosAndPoles
      import Modelica;
      import Modelica_LinearSystems2;
      import Modelica_LinearSystems2.ZerosAndPoles;
      import Modelica_LinearSystems2.Math.Vectors;
      import Modelica_LinearSystems2.Math.Complex;
      import Modelica_LinearSystems2.StateSpace;
      import Modelica_LinearSystems2.StateSpace.Internal;

      input ZerosAndPoles zp "ZerosAndPoles transfer function of a system";
      output StateSpace ss(
        redeclare Real A[ZerosAndPoles.Analysis.denominatorDegree(zp),
          ZerosAndPoles.Analysis.denominatorDegree(zp)],
        redeclare Real B[ZerosAndPoles.Analysis.denominatorDegree(zp),1],
        redeclare Real C[1,ZerosAndPoles.Analysis.denominatorDegree(zp)],
        redeclare Real D[1,1]) "Transfer function in StateSpace SISO form";

    protected
      Real A[2,2] "system matrix of partial 2nd order system";
      Real B[2,1] "input matrix of partial 2nd order system";
      Real C[1,2] "output matrix of partial 2nd order system";
      Real D[1,1] "feedthrough matrix of partial 2nd order system";
      Real a "system 'matrix' of partial 1st order system";
      Real b "input 'matrix' of partial 1st order system";
      Real c "output 'matrix' of partial 1st order system";
      Real d "feedthrough 'matrix' of partial 1st order system";
      Integer nx=ZerosAndPoles.Analysis.denominatorDegree(zp);
      Integer n_num1=size(zp.n1, 1);
      Integer n_num2=size(zp.n2, 1);
      Integer n_den1=size(zp.d1, 1);
      Integer n_den2=size(zp.d2, 1);
      Integer n_num=n_num1 + 2*n_num2;
      Integer n_den=n_den1 + 2*n_den2;

      Integer i_d=if n_num2 > n_den2 then 2*(n_num2 - n_den2) + 1 else 1;
      Integer i_k=if n_num2 > n_den2 then n_den2 - (n_num2 - n_den2) else n_den2;
      Integer i;
      Integer ili;
      Real num[nx,2]=[zp.n2; [zp.n1,zeros(n_num1)]; zeros(nx - n_num2 - n_num1, 2)]
        "Numerator matrix, in order that indices are defined in all situations in all if clauses";
      Real den[nx,2]=[zp.d2; [zp.d1,zeros(n_den1)]; zeros(nx - n_den2 - n_den1, 2)]
        "Denominator matrix, in order that indices are defined in all situations in all if clauses";
      Real k[i_k + n_den1](each fixed=false)
        "Additional factors of the first and second order blocks, in order that the gain of the blocks is 1";
      Real k_total;

      Boolean dZero=true;

     //ZerosAndPoles zp2;

    algorithm
      assert(n_num <= n_den,
        "ZerosAndPoles transfer function is not proper as required from StateSpace system:\n"
         + "  numerator degree (= " + String(n_num) +
        ") <= denominator degree (= " + String(n_den) + ") required.");

      if n_den > 0 then

        for i in 1:max(n_den2, n_num2) loop
          // State space systems of order 2
          if i <= n_den2 then
            if i <= n_num2 then
                // State space system in form (1)
              k[i] := Internal.scaleFactor2(
                  num[i, 1],
                  num[i, 2],
                  den[i, 1],
                  den[i, 2]);
            elseif i - n_num2 + 1 <= n_num1 then
                // State space system in form (1) with 2 first order numerator polynomials
              k[i] := Internal.scaleFactor2(
                  num[i, 1] + num[i + 1, 1],
                  num[i, 1]*num[i + 1, 1],
                  den[i, 1],
                  den[i, 2]);
            elseif i - n_num2 == n_num1 then
                // State space system in form (2) with 1 first order numerator polynomial
              k[i] := Internal.scaleFactor2(
                  0,
                  num[i, 1],
                  den[i, 1],
                  den[i, 2]);
            else
                // State space system in form (3)
              k[i] := Internal.scaleFactor2(
                  0,
                  0,
                  den[i, 1],
                  den[i, 2]);
            end if;
          else
             // State space system in form (1) with 2 first order denominator polynomials
            k[i] := Internal.scaleFactor2(
                num[i, 1],
                num[i, 2],
                den[i, 1] + den[i + 1, 1],
                den[i, 1]*den[i + 1, 1]);
          end if;
        end for;

        for i in i_d:n_den1 loop
          // State space systems of order 1
          if n_num2 <= n_den2 and 2*(n_den2 - n_num2) + i <= n_num1 then
             // State space system in form (4)
            k[i_k + i] := Internal.scaleFactor1(num[max(1, n_num2 + 2*(n_den2 -
              n_num2) + i), 1], den[n_den2 + i, 1]);
          elseif n_num2 > n_den2 and i - i_d + 1 <= n_num1 then
             // State space system in form (4)
            k[i_k + i] := Internal.scaleFactor1(num[max(1, n_num2 + i - i_d + 1),
              1], den[n_den2 + i, 1]);
          else
             // State space system in form (5)
            k[i_k + i] := Internal.scaleFactor1(0, den[n_den2 + i, 1]);
          end if;
        end for;

        k_total := zp.k/product(k);

        ss.A := zeros(nx, nx);
        ss.B := zeros(nx, 1);
        ss.C := zeros(1, nx);
        ss.D := zeros(1, 1);

     // Calculation of matrices A, B, C, D
     //first elements of A, B, C and D

        if max(n_den2, n_num2) > 0 then
          ili := i_d;
          A[1, :] := {0,1};
          B[1, 1] := 0;
              // Construct state space systems of order 2
          if 1 <= n_den2 then
            A[2, :] := {-den[1, 2],-den[1, 1]};
            B[2, 1] := den[1, 2];
            if 1 <= n_num2 then
                   // State space system in form (1)
              C := k[1]*[num[1, 2] - den[1, 2],num[1, 1] - den[1, 1]]/den[1, 2];
              D := [k[1]];
              dZero := false;

            elseif 1 - n_num2 + 1 <= n_num1 then
                   // State space system in form (1) with 2 first order numerator polynomials

              C := k[1]*[num[1, 1]*num[2, 1] - den[1, 2],num[1, 1] + num[2, 1] - den[1, 1]]/den[1, 2];
              D := [k[1]];
              dZero := false;
            elseif 1 - n_num2 == n_num1 then
                   // State space system in form (2) with 1 first order numerator polynomial

              C := k[1]*[num[1, 1],1]/den[1, 2];
              D := [0];
              dZero := dZero and true;
            else
                   // State space system in form (3)

              C := k[1]*[1,0]/den[1, 2];
              D := [0];
              dZero := dZero and true;
            end if;
          else
                // State space system in form (1) with 2 first order denominator polynomials

            A[2, :] := {-(den[1, 1]*den[2, 1]),-(den[1, 1] + den[2, 1])};
            B[2, 1] := den[1, 1]*den[1, 1];

            C := k[1]*[num[1, 2] - (den[1, 1]*den[2, 1]),num[1, 1] - (den[1, 1] + den[2, 1])]/den[1, 1]
              /den[1, 1];
            D := [k[1]];
            dZero := false;
          end if;
          ss.A[1:2, 1:2] := A;
          ss.B[1:2, 1] := vector(B);
          ss.C[1, 1:2] := vector(C);
          ss.D := D;

        else
          ili := max(2, i_d);
       // Construct state space systems of order 1
          a := -den[1, 1];
          b := den[1, 1];

          if 1 <= n_num1 then
                // State space system in form (4)
            c := k[1]*(num[1, 1] - den[1, 1])/den[1, 1];
            d := k[1];
            dZero := false;
          else
                // State space system in form (5)
            c := k[1]/den[1, 1];
            d := 0;
            dZero := dZero and true;
          end if;
          ss.A[1, 1] := a;
          ss.B[1, 1] := b;
          ss.C[1, 1] := c;
          ss.D[1, 1] := d;

        end if;

     /// for i=2 to degree(system)
        A[1, :] := {0,1};
        B[1, 1] := 0;

        for i in 2:max(n_den2, n_num2) loop
             // Construct state space systems of order 2
          if i <= n_den2 then
            A[2, :] := {-den[i, 2],-den[i, 1]};
            B[2, 1] := den[i, 2];

            if i <= n_num2 then
                   // State space system in form (1)

              C := k[i]*[num[i, 2] - den[i, 2],num[i, 1] - den[i, 1]]/den[i, 2];
              D := [k[i]];
              dZero := false;

            elseif i - n_num2 + 1 <= n_num1 then
                   // State space system in form (1) with 2 first order numerator polynomials
              C := k[i]*[num[i, 1]*num[i + 1, 1] - den[i, 2],num[i, 1] + num[i + 1, 1] - den[i, 1]]/den[
                i, 2];
              D := [k[i]];
              dZero := false;

            elseif i - n_num2 == n_num1 then
                   // State space system in form (2) with 1 first order numerator polynomial
              C := k[i]*[num[i, 1],1]/den[i, 2];
              D := [0];
              dZero := dZero and true;

            else
                   // State space system in form (3)
              C := k[i]*[1,0]/den[i, 2];
              D := [0];
              dZero := dZero and true;

            end if;

          else
                // State space system in form (1) with 2 first order denominator polynomials
            A[2, :] := {-(den[i, 1]*den[i + 1, 1]),-(den[i, 1] + den[i + 1, 1])};
            B[2, 1] := den[i, 1]*den[i, 1];

            C := k[i]*[num[i, 2] - (den[i, 1]*den[i + 1, 1]),num[i, 1] - (den[i, 1] + den[i + 1, 1])]/
              den[i, 1]/den[i, 1];
            D := [k[i]];
            dZero := false;
          end if;

          ss.A[2*i, 1:2*i - 2] := B[2, 1]*ss.C[1, 1:2*i - 2];
          ss.A[2*i - 1:2*i, 2*i - 1:2*i] := A;
          ss.B[2*i, 1] := if dZero then 0 else B[2, 1]*ss.D[1, 1];
          ss.C[1, 1:2*i - 2] := if dZero then fill(0, 2*i - 2) else D[1, 1]*ss.C[
            1, 1:2*i - 2];
          ss.C[1, 2*i - 1:2*i] := vector(C);
          ss.D := D*ss.D;
        end for;

     //  for i in max(2,i_d):n_den1 loop

        for i in ili:n_den1 loop
             // Construct state space systems of order 1
          a := if abs(den[n_den2 + i, 1])>Modelica.Constants.eps then -den[n_den2 + i, 1] else 0.0;
          b := if abs(den[n_den2 + i, 1])>Modelica.Constants.eps then den[n_den2 + i, 1] else 1.0;
          if n_num2 <= n_den2 and 2*(n_den2 - n_num2) + i <= n_num1 then
                // State space system in form (4)

            c := if abs(den[n_den2 + i, 1])>Modelica.Constants.eps then k[i_k + i]*(num[max(1, n_num2 + 2*(n_den2 - n_num2) + i), 1] -  den[n_den2 + i, 1])/den[n_den2 + i, 1] else 1.0;

            d := k[i_k + i];

            dZero := false;
          elseif n_num2 > n_den2 and i - i_d + 1 <= n_num1 then
                // State space system in form (4)

            c := if abs(den[n_den2 + i, 1])>Modelica.Constants.eps then k[i_k + i]*(num[max(1, n_num2 + i - i_d + 1), 1] - den[n_den2 + i, 1])/den[n_den2 + i, 1] else 1.0;
            d := k[i_k + i];
            dZero := false;
          else

                // State space system in form (5)

            c := k[i_k + i]/den[n_den2 + i, 1];
            d := 0;
            dZero := dZero and true;
          end if;

          ss.A[2*n_den2 + i, 1:2*n_den2 + i - 1] := b*ss.C[1, 1:2*n_den2 + i - 1];
          ss.A[2*n_den2 + i, 2*n_den2 + i] := a;
          ss.B[2*n_den2 + i, 1] := if dZero then 0 else b*ss.D[1, 1];
          ss.C[1, 1:2*n_den2 + i - 1] := if dZero then fill(0, 2*n_den2 + i - 1) else
                  d*ss.C[1, 1:2*n_den2 + i - 1];
          ss.C[1, 2*n_den2 + i] := c;
          ss.D := if dZero then [0] else d*ss.D;

        end for;
        ss.C := k_total*ss.C;
        ss.D := k_total*ss.D;
      else
        ss := Modelica_LinearSystems2.StateSpace(zp.k);
      end if;

    end toStateSpace;

## Modelica_LinearSystems2.ZerosAndPoles.Conversion.toMatrices

Convert a ZerosAndPoles object into the matrices A, B, C of a StateSpace

### Information

#### Syntax

ABCD | = | ZerosAndPoles.Conversion.toStateSpacetoStateSpace(tf)

#### Description

This function transforms a zeros-poles-gain system representation into state space representation. To achieve well numerical condition the ZerosAndPoles transfer function is transformed into state space form by creating first and second order blocks that are connected together in series. Every block is represented in controller canonical form and scaled such that the gain from the input of this block to its output is one (i.e. y(p=0) = u(p=0)), if this is possible. Details are given below.

Algorithmic details

The ZerosAndPoles transfer function is defined as:

>              product(p + n1[i]) * product(p^2 + n2[i,1]*p + n2[i,2])
>       y = k*--------------------------------------------------------- * u
>              product(p + d1[i]) * product(p^2 + d2[i,1]*p + d2[i,2])

This is treated as a series connection of first and second order systems. If size(n1) == size(d1) and size(n2) == size(d2) this gives the following sequence of operations:

>             p^2 + n2[1,1]*p + n2[1,2]
>       y_1 = ------------------------- * u
>             p^2 + d2[1,1]*p + d2[1,2]

>             p^2 + n2[2,1]*p + n2[2,2]
>       y_2 = ------------------------- * y_1
>             p^2 + d2[2,1]*p + d2[2,2]

>          ...

>             p + n1[..]
>       y_n = ---------- * y_(n-1)
>             p + d1[..]

>         y = k*y_n

Based on this representation, evrey block with transfer function G(p) could be transformed into

>       G(p) = k * F(p)

> with F(p) has unit gain. This leads to representations of the forms

>                a2 + a1*p + p^2       a2      b2 + a1*b2/a2*p + b2/a2*p^2
>       G(p) = -------------------- = ---- * ------------------------------ = k * F(p),  k = a2/b2  (1)

>                b2 + b1*p + p^2       b2           b2 + b1*p + p^2

>     for second order systems and

>                a + p     a     b + b/a*p
>       G(p) = -------- = --- * ---------- = k * F(p),   k = a/b

>                b + p     b      b + p

for first order systems respectively.

The complete system is now considered as the series connections of all the single unit gain transfer functions and an overall gain k with

>       k = product(ki).

In the general case, the following system structures and the corresponding state space systems can appear (note, 'c' is the reciprocal local gain 1/k):

>     (1)
>               a2 + a1*p + p^2           der(x1) = x2
>         y = ---------------------  -->  der(x2) = -b2*x1 - b1*x2 + b2*u
>               b2 + b1*p + p^2                 y = c*((a2-b2)*x1 + (a1-b1)*x2 + u),  c = b2/a2

>     (2)
>                  p + a                 der(x1) = x2
>         y = ---------------- * u  -->  der(x2) = -b2*x1 - b1*x2 + b2*u
>             b2 + b1*p + p^2                  y = k*(a1/b2*x1 +x2/b2),  c = b2/a

>     (3)
>                    1                  der(x1) = x2
>         y = --------------- *u   -->  der(x2) = -b2*x1 - b1*x2 + b2*u
>             b2 + b1*p + p^2                 y = c*x1/b2,  c = b2

>     (4)
>            a + p                       der(x) = -b*x + b*u
>        y = ----- * u             -->        y = c*((a-b)/b*x + u),  c = b/a
>            b + p

>     (5)
>              1
>        y = ----- * u             -->   der(x) = -b*x + b*u
>            b + p                            y = x,  c = b

If the sizes of the numerator and denominator polynomials do not match, the small systems are built in the following way:

>     (1) Build systems of form (1) by combining
>         - 1 d2 and 1 n2
>           (= 1 second order denominator and 1 second order numerator) or
>         - 1 d2 and 2 n1 or
>         - 2 d1 and 1 n2
>     (2) Build at most one system of form (2) by combining
>         - 1 d2 and 1 n2
>     (3) Build systems of form (3) by
>         - 1 d2
>     (4) Build systems of form (4) by combining
>         - 1 d1 and 1 n1
>     (5) Build systems of form (5) by
>         - 1 d1

The numeric properties of the resulting state space system depends on which first and second order polynomials are combined and connected together. From a numerical point of view, it would therefore be useful to combine the polynomials based on the numeric values of the polynomial coefficients, (e.g., in a first step the polynomials could be sorted according to their cut-off frequency).

However, this has the disadvantage that the structure of the resulting state space system depends on the numeric values of the polynomial coefficients. Since Modelica environments perform symbolic pre-processing on equations, this would mean that a change of a polynomial coefficient requires to newly compile the state space system.

If, on the other hand, the structure of the state space system depends only on dimension information of the n1,n2,d1,d2 arrays, then the polynomial coefficients can be changed without a new translation of the model. This is the major reason why the structure of the state space system in the implementation of this block is based only on dimension information.

This is, e.g., not critical for the provided filters: The dimension of the n1,n2,d1,d2 arrays depend for filters only on the filter characteristics (Bessel, Butterworth etc.), the filter type (low pass, high pass etc.) and on the filter order. If any of this data is changed, the model has to be newly compiled. All the other filter data, such as cut-off frequency or ripple amplitude, can be changed without re-compilation of the model. The ZerosAndPoles transfer function is now constructed for the filters in such a way that the filter zeros and poles are appropriately sorted to give better numerical properties.

Another alternative implementation of the state space system would be to use the function controller canonical form that directly results from the transfer function. The severe disadvantage of this approach is that the structure of the state space system from above is lost for the symbolic preprocessing. If, e.g., index reduction has to be applied (e.g. since a filter is used to realize a non-linear inverse model), then the tool cannot perform the index reduction. Example:

Assume, a generic first order state space system is present

>        der(x) = a*x + b*u
>             y = c*x + d*u

and the values of the scalars a,b,c,d are parameters that might be changed before the simulation starts. If y has to be differentiated symbolically during code generation, then

>           der(y) = c*der(x) + d*der(u)
>           der(x) = a*x + b*u

As a result, u needs to be differentiated too, and this might not be possible and therefore translation might fail.

On the other hand, if the first order system is defined to be a low pass filter and the state space system is generated by keeping this structure, we have (see form (5) above):

>       der(x) = -b*x + u
>             y = x

Differentiating y symbolically leads to:

>          der(y) = der(x)
>          der(x) = -b*x + u

Therefore, in this case, the derivative of u is not needed and the tool can continue with the symbolic processing.

#### Example

>        ZerosAndPoles p = Modelica_LinearSystems2.ZerosAndPoles.p();
>        Modelica_LinearSystems2.ZerosAndPoles zp=(p+1)/(p^2 + p +1);

>     algorithm
>       ABCD := Modelica_LinearSystems2.ZerosAndPoles.Conversion.toStateSpace(zp);
>     // ssA = [0, 1; -1, -1],
>     // ssB = [0; 1],
>     // ssC = [1, 1],
>     // ssD = [0],

### Inputs

Type | Name | Default | Description
--- | --- | --- | ---
ZerosAndPoles | zp |  | ZerosAndPoles transfer function of a system

### Outputs

Type | Name | Description
--- | --- | ---
Real | ABCD[ZerosAndPoles.Analysis.denominatorDegree(zp) + 1, ZerosAndPoles.Analysis.denominatorDegree(zp) + 1] |

### Modelica definition

    function toMatrices
      "Convert a ZerosAndPoles object into the matrices A, B, C of a StateSpace"
     //encapsulated function fromZerosAndPoles
      import Modelica;
      import Modelica_LinearSystems2;
      import Modelica_LinearSystems2.ZerosAndPoles;
      import Modelica_LinearSystems2.Math.Vectors;
      import Modelica_LinearSystems2.Math.Complex;
      import Modelica_LinearSystems2.StateSpace;
      import Modelica_LinearSystems2.StateSpace.Internal;

      input ZerosAndPoles zp "ZerosAndPoles transfer function of a system";
      output Real ABCD[ZerosAndPoles.Analysis.denominatorDegree(zp)+1,
          ZerosAndPoles.Analysis.denominatorDegree(zp)+1];

    protected
      Real ssA[ZerosAndPoles.Analysis.denominatorDegree(zp),ZerosAndPoles.Analysis.denominatorDegree(zp)]
        "system matrix of partial 2nd order system";
      Real ssB[ZerosAndPoles.Analysis.denominatorDegree(zp),1]
        "input matrix of partial 2nd order system";
      Real ssC[1,ZerosAndPoles.Analysis.denominatorDegree(zp)]
        "output matrix of partial 2nd order system";
      Real ssD[1,1] "feedthrough matrix of partial 2nd order system";

      Real A[2,2] "system matrix of partial 2nd order system";
      Real B[2,1] "input matrix of partial 2nd order system";
      Real C[1,2] "output matrix of partial 2nd order system";
      Real D[1,1] "feedthrough matrix of partial 2nd order system";
      Real a "system 'matrix' of partial 1st order system";
      Real b "input 'matrix' of partial 1st order system";
      Real c "output 'matrix' of partial 1st order system";
      Real d "feedthrough 'matrix' of partial 1st order system";
      Integer nx=ZerosAndPoles.Analysis.denominatorDegree(zp);
      Integer n_num1=size(zp.n1, 1);
      Integer n_num2=size(zp.n2, 1);
      Integer n_den1=size(zp.d1, 1);
      Integer n_den2=size(zp.d2, 1);
      Integer n_num=n_num1 + 2*n_num2;
      Integer n_den=n_den1 + 2*n_den2;

      Integer i_d=if n_num2 > n_den2 then 2*(n_num2 - n_den2) + 1 else 1;
      Integer i_k=if n_num2 > n_den2 then n_den2 - (n_num2 - n_den2) else n_den2;
      Integer i;
      Integer ili;
      Real num[nx,2]=[zp.n2; [zp.n1,zeros(n_num1)]; zeros(nx - n_num2 - n_num1, 2)]
        "Numerator matrix, in order that indices are defined in all situations in all if clauses";
      Real den[nx,2]=[zp.d2; [zp.d1,zeros(n_den1)]; zeros(nx - n_den2 - n_den1, 2)]
        "Denominator matrix, in order that indices are defined in all situations in all if clauses";
      Real k[i_k + n_den1](each fixed=false)
        "Additional factors of the first and second order blocks, in order that the gain of the blocks is 1";
      Real k_total;

      Boolean dZero=true;

     //ZerosAndPoles zp2;

    algorithm
      assert(n_num <= n_den,
        "ZerosAndPoles transfer function is not proper as required from StateSpace system:\n"
         + "  numerator degree (= " + String(n_num) +
        ") <= denominator degree (= " + String(n_den) + ") required.");

      if n_den > 0 then

        for i in 1:max(n_den2, n_num2) loop
          // State space systems of order 2
          if i <= n_den2 then
            if i <= n_num2 then
                // State space system in form (1)
              k[i] := Internal.scaleFactor2(
                  num[i, 1],
                  num[i, 2],
                  den[i, 1],
                  den[i, 2]);
            elseif i - n_num2 + 1 <= n_num1 then
                // State space system in form (1) with 2 first order numerator polynomials
              k[i] := Internal.scaleFactor2(
                  num[i, 1] + num[i + 1, 1],
                  num[i, 1]*num[i + 1, 1],
                  den[i, 1],
                  den[i, 2]);
            elseif i - n_num2 == n_num1 then
                // State space system in form (2) with 1 first order numerator polynomial
              k[i] := Internal.scaleFactor2(
                  0,
                  num[i, 1],
                  den[i, 1],
                  den[i, 2]);
            else
                // State space system in form (3)
              k[i] := Internal.scaleFactor2(
                  0,
                  0,
                  den[i, 1],
                  den[i, 2]);
            end if;
          else
             // State space system in form (1) with 2 first order denominator polynomials
            k[i] := Internal.scaleFactor2(
                num[i, 1],
                num[i, 2],
                den[i, 1] + den[i + 1, 1],
                den[i, 1]*den[i + 1, 1]);
          end if;
        end for;

        for i in i_d:n_den1 loop
          // State space systems of order 1
          if n_num2 <= n_den2 and 2*(n_den2 - n_num2) + i <= n_num1 then
             // State space system in form (4)
            k[i_k + i] := Internal.scaleFactor1(num[max(1, n_num2 + 2*(n_den2 -
              n_num2) + i), 1], den[n_den2 + i, 1]);
          elseif n_num2 > n_den2 and i - i_d + 1 <= n_num1 then
             // State space system in form (4)
            k[i_k + i] := Internal.scaleFactor1(num[max(1, n_num2 + i - i_d + 1),
              1], den[n_den2 + i, 1]);
          else
             // State space system in form (5)
            k[i_k + i] := Internal.scaleFactor1(0, den[n_den2 + i, 1]);
          end if;
        end for;

        k_total := zp.k/product(k);

        ssA := zeros(nx, nx);
        ssB := zeros(nx, 1);
        ssC := zeros(1, nx);
        ssD := zeros(1, 1);

     // Calculation of matrices A, B, C, D
     //first elements of A, B, C and D

        if max(n_den2, n_num2) > 0 then
          ili := i_d;
          A[1, :] := {0,1};
          B[1, 1] := 0;
              // Construct state space systems of order 2
          if 1 <= n_den2 then
            A[2, :] := {-den[1, 2],-den[1, 1]};
            B[2, 1] := den[1, 2];
            if 1 <= n_num2 then
                   // State space system in form (1)
              C := k[1]*[num[1, 2] - den[1, 2],num[1, 1] - den[1, 1]]/den[1, 2];
              D := [k[1]];
              dZero := false;

            elseif 1 - n_num2 + 1 <= n_num1 then
                   // State space system in form (1) with 2 first order numerator polynomials

              C := k[1]*[num[1, 1]*num[2, 1] - den[1, 2],num[1, 1] + num[2, 1] - den[1, 1]]/den[1, 2];
              D := [k[1]];
              dZero := false;
            elseif 1 - n_num2 == n_num1 then
                   // State space system in form (2) with 1 first order numerator polynomial

              C := k[1]*[num[1, 1],1]/den[1, 2];
              D := [0];
              dZero := dZero and true;
            else
                   // State space system in form (3)

              C := k[1]*[1,0]/den[1, 2];
              D := [0];
              dZero := dZero and true;
            end if;
          else
                // State space system in form (1) with 2 first order denominator polynomials

            A[2, :] := {-(den[1, 1]*den[2, 1]),-(den[1, 1] + den[2, 1])};
            B[2, 1] := den[1, 1]*den[1, 1];

            C := k[1]*[num[1, 2] - (den[1, 1]*den[2, 1]),num[1, 1] - (den[1, 1] + den[2, 1])]/den[1, 1]
              /den[1, 1];
            D := [k[1]];
            dZero := false;
          end if;
          ssA[1:2, 1:2] := A;
          ssB[1:2, 1] := vector(B);
          ssC[1, 1:2] := vector(C);
          ssD := D;

        else
          ili := max(2, i_d);
       // Construct state space systems of order 1
          a := -den[1, 1];
          b := den[1, 1];

          if 1 <= n_num1 then
                // State space system in form (4)
            c := k[1]*(num[1, 1] - den[1, 1])/den[1, 1];
            d := k[1];
            dZero := false;
          else
                // State space system in form (5)
            c := k[1]/den[1, 1];
            d := 0;
            dZero := dZero and true;
          end if;
          ssA[1, 1] := a;
          ssB[1, 1] := b;
          ssC[1, 1] := c;
          ssD[1, 1] := d;

        end if;

     /// for i=2 to degree(system)
        A[1, :] := {0,1};
        B[1, 1] := 0;

        for i in 2:max(n_den2, n_num2) loop
             // Construct state space systems of order 2
          if i <= n_den2 then
            A[2, :] := {-den[i, 2],-den[i, 1]};
            B[2, 1] := den[i, 2];

            if i <= n_num2 then
                   // State space system in form (1)

              C := k[i]*[num[i, 2] - den[i, 2],num[i, 1] - den[i, 1]]/den[i, 2];
              D := [k[i]];
              dZero := false;

            elseif i - n_num2 + 1 <= n_num1 then
                   // State space system in form (1) with 2 first order numerator polynomials
              C := k[i]*[num[i, 1]*num[i + 1, 1] - den[i, 2],num[i, 1] + num[i + 1, 1] - den[i, 1]]/den[
                i, 2];
              D := [k[i]];
              dZero := false;

            elseif i - n_num2 == n_num1 then
                   // State space system in form (2) with 1 first order numerator polynomial
              C := k[i]*[num[i, 1],1]/den[i, 2];
              D := [0];
              dZero := dZero and true;

            else
                   // State space system in form (3)
              C := k[i]*[1,0]/den[i, 2];
              D := [0];
              dZero := dZero and true;

            end if;

          else
                // State space system in form (1) with 2 first order denominator polynomials
            A[2, :] := {-(den[i, 1]*den[i + 1, 1]),-(den[i, 1] + den[i + 1, 1])};
            B[2, 1] := den[i, 1]*den[i, 1];

            C := k[i]*[num[i, 2] - (den[i, 1]*den[i + 1, 1]),num[i, 1] - (den[i, 1] + den[i + 1, 1])]/
              den[i, 1]/den[i, 1];
            D := [k[i]];
            dZero := false;
          end if;

          ssA[2*i, 1:2*i - 2] := B[2, 1]*ssC[1, 1:2*i - 2];
          ssA[2*i - 1:2*i, 2*i - 1:2*i] := A;
          ssB[2*i, 1] := if dZero then 0 else B[2, 1]*ssD[1, 1];
          ssC[1, 1:2*i - 2] := if dZero then fill(0, 2*i - 2) else D[1, 1]*ssC[
            1, 1:2*i - 2];
          ssC[1, 2*i - 1:2*i] := vector(C);
          ssD := D*ssD;
        end for;

     //  for i in max(2,i_d):n_den1 loop

        for i in ili:n_den1 loop
             // Construct state space systems of order 1
          a := if abs(den[n_den2 + i, 1])>Modelica.Constants.eps then -den[n_den2 + i, 1] else 0.0;
          b := if abs(den[n_den2 + i, 1])>Modelica.Constants.eps then den[n_den2 + i, 1] else 1.0;
          if n_num2 <= n_den2 and 2*(n_den2 - n_num2) + i <= n_num1 then
                // State space system in form (4)

            c := if abs(den[n_den2 + i, 1])>Modelica.Constants.eps then k[i_k + i]*(num[max(1, n_num2 + 2*(n_den2 - n_num2) + i), 1] -  den[n_den2 + i, 1])/den[n_den2 + i, 1] else 1.0;

            d := k[i_k + i];

            dZero := false;
          elseif n_num2 > n_den2 and i - i_d + 1 <= n_num1 then
                // State space system in form (4)

            c := if abs(den[n_den2 + i, 1])>Modelica.Constants.eps then k[i_k + i]*(num[max(1, n_num2 + i - i_d + 1), 1] - den[n_den2 + i, 1])/den[n_den2 + i, 1] else 1.0;
            d := k[i_k + i];
            dZero := false;
          else

                // State space system in form (5)

            c := k[i_k + i]/den[n_den2 + i, 1];
            d := 0;
            dZero := dZero and true;
          end if;

          ssA[2*n_den2 + i, 1:2*n_den2 + i - 1] := b*ssC[1, 1:2*n_den2 + i - 1];
          ssA[2*n_den2 + i, 2*n_den2 + i] := a;
          ssB[2*n_den2 + i, 1] := if dZero then 0 else b*ssD[1, 1];
          ssC[1, 1:2*n_den2 + i - 1] := if dZero then fill(0, 2*n_den2 + i - 1) else
                  d*ssC[1, 1:2*n_den2 + i - 1];
          ssC[1, 2*n_den2 + i] := c;
          ssD := if dZero then [0] else d*ssD;

        end for;
        ssC := k_total*ssC;
        ssD := k_total*ssD;
      else
        ABCD := [zp.k];
      end if;

      ABCD := [ssA,ssB; ssC,ssD];

    end toMatrices;