Skip to content

Use SLICOT's TB05AD in Statespace.freqresp #116

Closed
@roryyorke

Description

@roryyorke

StateSpace.freqresp current converts to a transfer-function matrix (TFM) to evaluate the frequency response (see [1]) .

Polynomials can give numerical problems (see below), so this method should probably use [2] (unfortunately not currently exposed in Slycot). This technique uses an orthogonal similarity transform to make the system quicker to evaluate.

One possible problem is that if one evaluates a decoupled (diagonal TFM) system in which one system has poles on the imaginary axis, I imagine the whole frequency response will be infinite. I'm not sure if this is really important.

[1]

# when evaluating at many frequencies, much faster to convert to

[2] http://slicot.org/objects/software/shared/doc/TB05AD.html

A script to demonstrate the problem:

import numpy as np
import control

wn = 1;
zeta = 0.01;
g = control.tf(wn**2, [1,2*zeta*wn,wn**2])

def trivial_evalfr(gss,w):
    I = np.eye(*gss.A.shape)
    return np.dot(gss.C,np.linalg.solve(1j*w*I-gss.A,gss.B)) + gss.D

def trivpow(g,n):
    from functools import reduce
    from operator import mul
    assert g.inputs == g.outputs
    I = np.eye(g.inputs)
    return reduce(mul,[g for i in range(n)])

gss = control.ss(g)

print()
print('{:3s} {:>9s} {:>9s} {:>9s} {:>9s}'.format('exp','tfv/ref','tfv/ref','ssv/ref','ssv/ref'))
print('{:3s} {:>9s} {:>9s} {:>9s} {:>9s}'.format('','1','dB','1','dB'))

exps = range(1,21)

gtfs = [trivpow(g,i)
        for i in exps]
gsss = [trivpow(gss,i)
        for i in exps]

for exp,gtfi,gssi in zip(exps,gtfs,gsss):
    ref = g.evalfr(1)**exp
    tfv = gtfi.evalfr(1)
    ssv = trivial_evalfr(gssi,1)

    tferr = np.abs(tfv/ref)[0,0]
    sserr = np.abs(ssv/ref)[0,0]

    db = lambda x: 20*np.log10(x)
    print('{:3d} {:9.2e} {:9.2e} {:9.2e} {:9.2e}'.format(exp,tferr,db(tferr),sserr,db(sserr)))

result is

exp   tfv/ref   tfv/ref   ssv/ref   ssv/ref
            1        dB         1        dB
  1  1.00e+00  0.00e+00  1.00e+00 -6.75e-15
  2  1.00e+00  9.57e-13  1.00e+00 -1.54e-14
  3  1.00e+00 -8.69e-12  1.00e+00 -2.41e-14
  4  1.00e+00 -4.36e-08  1.00e+00 -3.18e-14
  5  1.00e+00  1.10e-07  1.00e+00 -3.95e-14
  6  1.00e+00  7.16e-05  1.00e+00 -4.82e-14
  7  1.00e+00  1.65e-03  1.00e+00 -5.40e-14
  8  9.01e-01 -9.08e-01  1.00e+00 -6.27e-14
  9  2.88e-02 -3.08e+01  1.00e+00 -7.04e-14
 10  2.51e-04 -7.20e+01  1.00e+00 -8.00e-14
 11  2.27e-05 -9.29e+01  1.00e+00 -8.68e-14
 12  7.62e-08 -1.42e+02  1.00e+00 -9.35e-14
 13  6.38e-10 -1.84e+02  1.00e+00 -1.03e-13
 14  1.38e-11 -2.17e+02  1.00e+00 -1.09e-13
 15  4.16e-13 -2.48e+02  1.00e+00 -1.20e-13
 16  1.76e-15 -2.95e+02  1.00e+00 -1.25e-13
 17  1.13e-17 -3.39e+02  1.00e+00 -1.33e-13
 18  2.74e-20 -3.91e+02  1.00e+00 -1.41e-13
 19  6.49e-22 -4.24e+02  1.00e+00 -1.49e-13
 20  1.72e-24 -4.75e+02  1.00e+00 -1.56e-13

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions