|
35 | 35 | # Author: M.M. (Rene) van Paassen (using xferfcn.py as basis) |
36 | 36 | # Date: 02 Oct 12 |
37 | 37 |
|
38 | | -from __future__ import division |
39 | 38 |
|
40 | 39 | """ |
41 | 40 | Frequency response data representation and functions. |
|
48 | 47 | from warnings import warn |
49 | 48 | import numpy as np |
50 | 49 | from numpy import angle, array, empty, ones, \ |
51 | | - real, imag, absolute, eye, linalg, where, dot, sort |
| 50 | + real, imag, absolute, eye, linalg, where, sort |
52 | 51 | from scipy.interpolate import splprep, splev |
53 | 52 | from .lti import LTI, _process_frequency_response |
54 | 53 | from . import config |
@@ -302,7 +301,7 @@ def __mul__(self, other): |
302 | 301 | fresp = empty((outputs, inputs, len(self.omega)), |
303 | 302 | dtype=self.fresp.dtype) |
304 | 303 | for i in range(len(self.omega)): |
305 | | - fresp[:, :, i] = dot(self.fresp[:, :, i], other.fresp[:, :, i]) |
| 304 | + fresp[:, :, i] = self.fresp[:, :, i] @ other.fresp[:, :, i] |
306 | 305 | return FRD(fresp, self.omega, |
307 | 306 | smooth=(self.ifunc is not None) and |
308 | 307 | (other.ifunc is not None)) |
@@ -330,7 +329,7 @@ def __rmul__(self, other): |
330 | 329 | fresp = empty((outputs, inputs, len(self.omega)), |
331 | 330 | dtype=self.fresp.dtype) |
332 | 331 | for i in range(len(self.omega)): |
333 | | - fresp[:, :, i] = dot(other.fresp[:, :, i], self.fresp[:, :, i]) |
| 332 | + fresp[:, :, i] = other.fresp[:, :, i] @ self.fresp[:, :, i] |
334 | 333 | return FRD(fresp, self.omega, |
335 | 334 | smooth=(self.ifunc is not None) and |
336 | 335 | (other.ifunc is not None)) |
@@ -536,20 +535,15 @@ def feedback(self, other=1, sign=-1): |
536 | 535 | if (self.noutputs != other.ninputs or self.ninputs != other.noutputs): |
537 | 536 | raise ValueError( |
538 | 537 | "FRD.feedback, inputs/outputs mismatch") |
539 | | - fresp = empty((self.noutputs, self.ninputs, len(other.omega)), |
540 | | - dtype=complex) |
541 | | - # TODO: vectorize this |
| 538 | + |
542 | 539 | # TODO: handle omega re-mapping |
543 | | - # TODO: is there a reason to use linalg.solve instead of linalg.inv? |
544 | | - # https://github.com/python-control/python-control/pull/314#discussion_r294075154 |
545 | | - for k, w in enumerate(other.omega): |
546 | | - fresp[:, :, k] = np.dot( |
547 | | - self.fresp[:, :, k], |
548 | | - linalg.solve( |
549 | | - eye(self.ninputs) |
550 | | - + np.dot(other.fresp[:, :, k], self.fresp[:, :, k]), |
551 | | - eye(self.ninputs)) |
552 | | - ) |
| 540 | + |
| 541 | + # reorder array axes in order to leverage numpy broadcasting |
| 542 | + myfresp = np.moveaxis(self.fresp, 2, 0) |
| 543 | + otherfresp = np.moveaxis(other.fresp, 2, 0) |
| 544 | + I_AB = eye(self.ninputs)[np.newaxis, :, :] + otherfresp @ myfresp |
| 545 | + resfresp = (myfresp @ linalg.inv(I_AB)) |
| 546 | + fresp = np.moveaxis(resfresp, 0, 2) |
553 | 547 |
|
554 | 548 | return FRD(fresp, other.omega, smooth=(self.ifunc is not None)) |
555 | 549 |
|
|
0 commit comments