def spectral_radius(model): if not isinstance(model, sys.dlti): model = sys.dlti(*model) poles = model.poles if poles.size == 0: return None return np.max(np.absolute(poles))
def output_range(model, input_range): if not isinstance(model, sys.dlti): model = sys.dlti(*model) if not isinstance(input_range, Interval): input_range = Interval(input_range) mean_input = (input_range.upper_bound + input_range.lower_bound) / 2 input_delta = (input_range.upper_bound - input_range.lower_bound) / 2 if model.inputs > 1: mean_output = dc_gain(model) @ mean_input output_delta = worst_case_peak_gain(model) @ input_delta else: mean_output = dc_gain(model) * mean_input output_delta = worst_case_peak_gain(model) * input_delta if model.outputs == 1: mean_output = asscalar_if_possible(mean_output) output_delta = asscalar_if_possible(output_delta) a = mean_output - output_delta b = mean_output + output_delta return Interval(np.min([a, b], axis=0), np.max([a, b], axis=0))
def worst_case_peak_gain(model): if not isinstance(model, sys.dlti): model = sys.dlti(*model) if isinstance(model, sys.StateSpaceDiscrete): return WCPG_ABCD(model.A.astype(np.float64), model.B.astype(np.float64), model.C.astype(np.float64), model.D.astype(np.float64)) if isinstance(model, sys.TransferFunctionDiscrete): if model.outputs != 1: raise NotImplementedError('SISO transfer functions only') return worst_case_peak_gain(model.to_ss())[0, 0] raise TypeError(f'Cannot compute worst case peak gain of {model}')
def dc_gain(model): if not isinstance(model, sys.dlti): model = sys.dlti(*model) if isinstance(model, sys.ZerosPolesGainDiscrete): model = model.to_tf() if isinstance(model, sys.TransferFunctionDiscrete): if model.outputs != 1: raise NotImplementedError('SISO transfer functions only') return np.sum(model.num) / np.sum(model.den) if isinstance(model, sys.StateSpaceDiscrete): return model.C @ np.linalg.inv(np.eye(*model.A.shape) - model.A) @ model.B + model.D raise TypeError(f'Cannot compute DC gain of {model}')
def is_stable(model, tol=1e-16): if not isinstance(model, sys.dlti): model = sys.dlti(*model) return np.all(np.absolute(model.poles) < (1. - tol))