pyyeti.expmint.getEPQ2

pyyeti.expmint.getEPQ2(A, h, order=1, B=None, half=False)[source]

Returns E, P, Q for the exponential solver given the state-space matrix A.

Parameters:
  • A (2d ndarray) – The state-space matrix: xdot = A x + B u

  • h (scalar) – Time step.

  • order (integer, optional) –

    • 0 for the zero order hold (force stays constant across time step)

    • 1 for the 1st order hold (force can vary linearly across time step)

  • B (d2 ndarray or None; optional) – If array, it multiplies the inputs; if None, it is assumed identity.

  • half (bool; optional) – If B is a 2d ndarray, half is ignored. Otherwise, if half is False, a full size identity (same size as A) is used for B. If half is True, only the first half of the columns are retained (which is handy for converting a 2nd order ODE into a 1st order ODE as pyyeti.ode.SolveExp2 does – where there are force inputs only for the first half of the equations).

Returns:

E, P, Q (2d ndarrays, except if order == 0, Q = 0.) –

These are the coefficient matrices used to solve the ODE:

for j in range(nt):
    d[:, j+1] = E*d[:, j] + P*F[:, j] + Q*F[:, j+1]

Notes

Normally, getEPQ() would be called and that routine will call this one or getEPQ1().

This routine is an alternative to getEPQ1() and is generally slower but more robust for large time steps. (If B has only a few columns, it could also be faster than getEPQ1().) E is the matrix exponential exp(A*h) and P and Q are functions of the integral(s) of the matrix exponential. They are calculated as follows (text from scipy.signal.lsim()).

If order == 0:

Zero-order hold
Algorithm: to integrate from time 0 to time dt, we solve
  xdot = A x + B u,  x(0) = x0
  udot = 0,          u(0) = u0.

Solution is
  [ x(dt) ]       [ A*dt   B*dt ] [ x0 ]
  [ u(dt) ] = exp [  0     0    ] [ u0 ]

The E, and P matrices are partitions of the matrix exponential and Q is zero.

If order == 1:

Linear interpolation between steps
Algorithm: to integrate from time 0 to time dt, with
linear interpolation between inputs u(0) = u0 and u(dt) = u1,
we solve:
  xdot = A x + B u,        x(0) = x0
  udot = (u1 - u0) / dt,   u(0) = u0.

Solution is
  [ x(dt) ]       [ A*dt  B*dt  0 ] [  x0   ]
  [ u(dt) ] = exp [  0     0    I ] [  u0   ]
  [u1 - u0]       [  0     0    0 ] [u1 - u0]

The E, P and Q matrices are partitions of the matrix exponential.

Examples

>>> from pyyeti import expmint
>>> import numpy as np
>>> import scipy.linalg as la
>>> np.set_printoptions(4)
>>> A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> B = np.array([[0, 1, 0]]).T
>>> E, P, Q = expmint.getEPQ2(A, .05, order=1, B=B)
>>> E
array([[ 1.0996,  0.1599,  0.2202],
       [ 0.3099,  1.3849,  0.46  ],
       [ 0.5202,  0.61  ,  1.6998]])
>>> P
array([[ 0.0024],
       [ 0.0308],
       [ 0.0091]])
>>> Q
array([[ 0.0011],
       [ 0.0276],
       [ 0.0041]])
>>> E, P, Q = expmint.getEPQ2(A, .05, order=0, B=B)
>>> E
array([[ 1.0996,  0.1599,  0.2202],
       [ 0.3099,  1.3849,  0.46  ],
       [ 0.5202,  0.61  ,  1.6998]])
>>> P
array([[ 0.0034],
       [ 0.0583],
       [ 0.0133]])
>>> Q
0.0