ilayn/harold

numerical issue creating transfer function

twmacro opened this issue · 3 comments

Hi!

I'm getting an error trying to create a transfer function. Below is a little example that shows the error on my computer. I'm thinking that somehow a numeric leading "zero" shows up (it was -8.3948810935738183e-17 for me) and is not trimmed off by np.trim_zeros. That creates sizing trouble when assembling the state-space matrices.

import harold


# set up a 2-input, 1-output transfer function

# denominator is the same for both transfer functions:
den = [[[[84.64, 18.4, 1.0]], [[1.0, 7.2, 144.0]]]]

# - same as below except last 4 digits chopped off for each number
num = [
    [
        [[61.7973249220, 36.2498843026, 0.730119623369]],
        [[0.037784067405, 0.997499379512, 21.76362282573]],
    ]
]

# this one works:
tf1 = harold.Transfer(num, den)
print(tf1)

# keep those last 4 digits and it breaks:
num = [
    [
        [[61.79732492202783, 36.24988430260625, 0.7301196233698941]],
        [[0.0377840674057878, 0.9974993795127982, 21.763622825733773]],
    ]
]

tf2 = harold.Transfer(num, den)
print(tf2)

And here is the output:

Continuous-Time Transfer function
 2 inputs and 1 output

  Poles(real)    Poles(imag)  Zeros(real)    Zeros(imag)
-------------  -------------  -------------  -------------
    -0.108696    1.16214e-07
    -0.108696   -1.16214e-07
    -3.6        11.4473
    -3.6       -11.4473


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~/code/harold/bug.py in <module>
     27 ]
     28
---> 29 tf2 = harold.Transfer(num, den)
     30 print(tf2)

~/code/harold/harold/_classes.py in __init__(self, num, den, dt)
     70         self._isdiscrete = False if dt is None else True
     71
---> 72         self._recalc()
     73
     74     @property

~/code/harold/harold/_classes.py in _recalc(self)
    302                 # Create a dummy statespace and check the zeros there
    303                 zzz = transfer_to_state((self._num, self._den),
--> 304                                         output='matrices')
    305                 self.zeros = transmission_zeros(*zzz)
    306                 self.poles = eigvals(zzz[0])

~/code/harold/harold/_classes.py in transfer_to_state(G, output)
   3036
   3037                 for row in range(p):
-> 3038                     C[row, k:k+num[row][col].size] = num[row][col][0, ::-1]
   3039                 k += coldegrees[col]
   3040

ValueError: could not broadcast input array from shape (5) into shape (4)
ilayn commented

Thanks @twmacro for taking the time. After briefly looking at it, I think your hunch is correct. I will take a look after work.

Fantastic! Thank you @ilayn!

ilayn commented

My pleasure @twmacro . Keep them coming:)