Search code examples
matrixmodelicaexponentialopenmodelicadiscretization

LTI state-space model discretization using Modelica integralExp function not working


I need to perform a ZOH discretization of a continuous LTI state-space model in OpenModelica (OMEdit). I tried two ways of doing this:

  1. using matrix exponential (Matrices.exp function) for calculating discretized A matrix (Ad) and subsequent calculation of discretized B matrix (Bd) following equation: Bd = A-1 (Ad - I) B, where I is identity matrix; This algebraic equation can be solved either by direct calculation of matrix inversion (Matrices.inv function) or, more efficiently, by solving for Bd matrix using Matrices.solve2 function: Bd = Matrices.solve2(A,(Ad-identity(2))), thus avoiding calculation of matrix inversion. However, in both cases A matrix must be invertible, what generally (and very often) doesn't hold.
  2. using Matrices.integralExp function which should return both discretized matrices (Ad, Bd) and should work for general matrix A, whether invertible or singular; However, this function does not work for me - it returns error message: "No viable alternative near token: (".

I attach code for both methods for demonstration purpose. The state space model represents a very simple second-order system of linearized pendulum with length 1 m, mass 1 kg and gravitational acceleration 9.81 m/s2. Sampling time for discretization is 0.1 s. The first code works fine (A is invertible in this particular case) but the second code doesn't. Does anybody know what am I doing wrong? I'd be grateful for any advice.

method #1:

model ssDiscretization
  import Modelica.Math.Matrices;
  // Continuous LTI state-space model of pendulum: L=1, m=1, g=9.81
  Real A[2,2] = [0, 1; -9.81, 0] "system matrix";
  Real B[2,1] = [0; 1] "input matrix";
  // Discretization with sampling time 0.1 s
  Real Ad[2,2] = Matrices.exp(A,0.1) "T = 0.1 s";
  Real Bd[2,1] = Matrices.inv(A)*(Ad - identity(2))*B;
end ssDiscretization;

method #2:

model ssDiscretization
  import Modelica.Math.Matrices;
  // Continuous LTI state-space model of pendulum: L=1, m=1, g=9.81
  Real A[2,2] = [0, 1; -9.81, 0] "system matrix";
  Real B[2,1] = [0; 1] "input matrix";
  // Discretization with sampling time 0.1 s
  Real Ad[2,2];
  Real Bd[2,1];
  (Ad,Bd) = Matrices.integralExp(A,B,0.1) "T = 0.1 s";
end ssDiscretization;

Oliver


Solution

  • You forgot the equation keyword in example 2. It still won't work in OpenModelica since it seems to have a problem with the alias na=size(A,1) in that function but you could easily fix the source code to make that work.

    model ssDiscretization
      import Modelica.Math.Matrices;
      // Continuous LTI state-space model of pendulum: L=1, m=1, g=9.81
      Real A[2,2] = [0, 1; -9.81, 0] "system matrix";
      Real B[2,1] = [0; 1] "input matrix";
      // Discretization with sampling time 0.1 s
      Real Ad[2,2];
      Real Bd[2,1];
    equation // This was missing
      (Ad,Bd) = Matrices.integralExp(A,B,0.1) "T = 0.1 s";
    end ssDiscretization;