) fig, ax = plt.subplots() so_sys.mag_plot(w, ax=ax) rom_bt.mag_plot(w, ax=ax, linestyle='dashed') ax.set_title('Magnitude plot of the full and BT reduced model') plt.show() fig, ax = plt.subplots() err_bt.mag_plot(w, ax=ax) ax.set_title('Magnitude plot of the BT error system') plt.show() # Iterative Rational Krylov Algorithm (IRKA) r = 5 irka_reductor = IRKAReductor(so_sys.to_lti()) rom_irka = irka_reductor.reduce(r) fig, ax = plt.subplots() ax.semilogy(irka_reductor.conv_crit, '.-') ax.set_title('IRKA convergence criterion') plt.show() poles_rom_irka = rom_irka.poles() fig, ax = plt.subplots() ax.plot(poles_rom_irka.real, poles_rom_irka.imag, '.') ax.set_title("IRKA reduced model's poles") plt.show() err_irka = so_sys - rom_irka print(
print(f'BT relative Hankel-error: {err_bt.hankel_norm() / so_sys.hankel_norm():e}') fig, ax = plt.subplots() so_sys.mag_plot(w, ax=ax) rom_bt.mag_plot(w, ax=ax, linestyle='dashed') ax.set_title('Bode plot of the full and BT reduced model') plt.show() fig, ax = plt.subplots() err_bt.mag_plot(w, ax=ax) ax.set_title('Bode plot of the BT error system') plt.show() # Iterative Rational Krylov Algorithm (IRKA) r = 5 irka_reductor = IRKAReductor(so_sys.to_lti()) rom_irka = irka_reductor.reduce(r) fig, ax = plt.subplots() ax.semilogy(irka_reductor.conv_crit, '.-') ax.set_title('IRKA convergence criterion') plt.show() poles_rom_irka = rom_irka.poles() fig, ax = plt.subplots() ax.plot(poles_rom_irka.real, poles_rom_irka.imag, '.') ax.set_title("IRKA reduced model's poles") plt.show() err_irka = so_sys - rom_irka print(f'IRKA relative H_2-error: {err_irka.h2_norm() / so_sys.h2_norm():e}')
def reduce(self, rom0_params, tol=1e-4, maxit=100, num_prev=1, force_sigma_in_rhp=False, projection='orth', conv_crit='sigma', compute_errors=False, irka_options=None): r"""Reduce using SOR-IRKA. It uses IRKA as the intermediate reductor, to reduce from 2r to r poles. See Section 5.3.2 in [W12]_. Parameters ---------- rom0_params Can be: - order of the reduced model (a positive integer), - dict with `'sigma'`, `'b'`, `'c'` as keys mapping to initial interpolation points (a 1D |NumPy array|), right tangential directions (|VectorArray| from `fom.input_space`), and left tangential directions (|VectorArray| from `fom.output_space`), all of the same length (the order of the reduced model), - initial reduced-order model (|LTIModel|). If the order of reduced model is given, initial interpolation data is generated randomly. tol Tolerance for the convergence criterion. maxit Maximum number of iterations. num_prev Number of previous iterations to compare the current iteration to. Larger number can avoid occasional cyclic behavior of IRKA. force_sigma_in_rhp If `False`, new interpolation are reflections of the current reduced order model's poles. Otherwise, only the poles in the left half-plane are reflected. projection Projection method: - `'orth'`: projection matrices are orthogonalized with respect to the Euclidean inner product - `'biorth'`: projection matrices are biorthogolized with respect to the E product conv_crit Convergence criterion: - `'sigma'`: relative change in interpolation points - `'h2'`: relative :math:`\mathcal{H}_2` distance of reduced-order models compute_errors Should the relative :math:`\mathcal{H}_2`-errors of intermediate reduced order models be computed. .. warning:: Computing :math:`\mathcal{H}_2`-errors is expensive. Use this option only if necessary. irka_options Dict of options for IRKAReductor.reduce. Returns ------- rom Reduced-order |SecondOrderModel|. """ if not self.fom.cont_time: raise NotImplementedError self._clear_lists() sigma, b, c = self._rom0_params_to_sigma_b_c(rom0_params, force_sigma_in_rhp) self._store_sigma_b_c(sigma, b, c) self._check_common_args(tol, maxit, num_prev, conv_crit) assert projection in ('orth', 'biorth') assert irka_options is None or isinstance(irka_options, dict) if not irka_options: irka_options = {} self.logger.info('Starting SOR-IRKA') self._conv_data = (num_prev + 1) * [None] if conv_crit == 'sigma': self._conv_data[0] = sigma self._pg_reductor = SOBHIReductor(self.fom, mu=self.mu) for it in range(maxit): rom = self._pg_reductor.reduce(sigma, b, c, projection=projection) with self.logger.block('Intermediate reduction ...'): irka_reductor = IRKAReductor(rom.to_lti()) rom_r = irka_reductor.reduce(rom.order, **irka_options) sigma, b, c = self._rom_to_sigma_b_c(rom_r, force_sigma_in_rhp) self._store_sigma_b_c(sigma, b, c) self._update_conv_data(sigma, rom, conv_crit) self._compute_conv_crit(rom, conv_crit, it) self._compute_error(rom, it, compute_errors) if self.conv_crit[-1] < tol: break self.V = self._pg_reductor.V self.W = self._pg_reductor.W return rom
ax.semilogy(mu_fine, hinf_bt_err_mu, '.-', label=r'$\mathcal{H}_\infty$') ax.semilogy(mu_fine, hankel_bt_err_mu, '.-', label='Hankel') ax.set_xlabel(r'$\mu$') ax.set_title('Balanced truncation errors') ax.legend() #plot.sho() # # Iterative Rational Krylov Algorithm (IRKA) # In[ ]: (h2_irka_err_mu, hinf_irka_err_mu, hankel_irka_err_mu) = reduction_errors( lti, r, mu_fine, lambda lti, r, mu=mu: IRKAReductor(lti, mu=mu).reduce(r, conv_crit='h2')) # In[ ]: fig, ax = plt.subplots() ax.semilogy(mu_fine, h2_irka_err_mu, '.-', label=r'$\mathcal{H}_2$') if config.HAVE_SLYCOT: ax.semilogy(mu_fine, hinf_irka_err_mu, '.-', label=r'$\mathcal{H}_\infty$') ax.semilogy(mu_fine, hankel_irka_err_mu, '.-', label='Hankel') ax.set_xlabel(r'$\mu$') ax.set_title('IRKA errors') ax.legend() #plot.sho()
def main( n: int = Argument( 101, help='Order of the full second-order model (odd number).'), r: int = Argument(5, help='Order of the ROMs.'), ): """String equation example.""" set_log_levels({'pymor.algorithms.gram_schmidt.gram_schmidt': 'ERROR'}) # Assemble matrices assert n % 2 == 1, 'The order has to be an odd integer.' n2 = (n + 1) // 2 d = 10 # damping k = 0.01 # stiffness M = sps.eye(n, format='csc') E = d * sps.eye(n, format='csc') K = sps.diags( [n * [2 * k * n**2], (n - 1) * [-k * n**2], (n - 1) * [-k * n**2]], [0, -1, 1], format='csc') B = np.zeros((n, 1)) B[n2 - 1, 0] = n Cp = np.zeros((1, n)) Cp[0, n2 - 1] = 1 # Second-order system so_sys = SecondOrderModel.from_matrices(M, E, K, B, Cp) print(f'order of the model = {so_sys.order}') print(f'number of inputs = {so_sys.dim_input}') print(f'number of outputs = {so_sys.dim_output}') poles = so_sys.poles() fig, ax = plt.subplots() ax.plot(poles.real, poles.imag, '.') ax.set_title('System poles') plt.show() w = np.logspace(-4, 2, 200) fig, ax = plt.subplots() so_sys.mag_plot(w, ax=ax) ax.set_title('Magnitude plot of the full model') plt.show() psv = so_sys.psv() vsv = so_sys.vsv() pvsv = so_sys.pvsv() vpsv = so_sys.vpsv() fig, ax = plt.subplots(2, 2, figsize=(12, 8), sharey=True) ax[0, 0].semilogy(range(1, len(psv) + 1), psv, '.-') ax[0, 0].set_title('Position singular values') ax[0, 1].semilogy(range(1, len(vsv) + 1), vsv, '.-') ax[0, 1].set_title('Velocity singular values') ax[1, 0].semilogy(range(1, len(pvsv) + 1), pvsv, '.-') ax[1, 0].set_title('Position-velocity singular values') ax[1, 1].semilogy(range(1, len(vpsv) + 1), vpsv, '.-') ax[1, 1].set_title('Velocity-position singular values') plt.show() print(f'FOM H_2-norm: {so_sys.h2_norm():e}') if config.HAVE_SLYCOT: print(f'FOM H_inf-norm: {so_sys.hinf_norm():e}') else: print('H_inf-norm calculation is skipped due to missing slycot.') print(f'FOM Hankel-norm: {so_sys.hankel_norm():e}') # Model order reduction run_mor_method(so_sys, w, SOBTpReductor(so_sys), 'SOBTp', r) run_mor_method(so_sys, w, SOBTvReductor(so_sys), 'SOBTv', r) run_mor_method(so_sys, w, SOBTpvReductor(so_sys), 'SOBTpv', r) run_mor_method(so_sys, w, SOBTvpReductor(so_sys), 'SOBTvp', r) run_mor_method(so_sys, w, SOBTfvReductor(so_sys), 'SOBTfv', r) run_mor_method(so_sys, w, SOBTReductor(so_sys), 'SOBT', r) run_mor_method(so_sys, w, SORIRKAReductor(so_sys), 'SOR-IRKA', r, irka_options={'maxit': 10}) run_mor_method(so_sys, w, BTReductor(so_sys.to_lti()), 'BT', r) run_mor_method(so_sys, w, IRKAReductor(so_sys.to_lti()), 'IRKA', r)
def reduce(self, r, sigma=None, b=None, c=None, rom0=None, tol=1e-4, maxit=100, num_prev=1, force_sigma_in_rhp=False, projection='orth', conv_crit='sigma', compute_errors=False, irka_options=None): r"""Reduce using SOR-IRKA. It uses IRKA as the intermediate reductor, to reduce from 2r to r poles. See Section 5.3.2 in [W12]_. Parameters ---------- r Order of the reduced order model. sigma Initial interpolation points (closed under conjugation). If `None`, interpolation points are log-spaced between 0.1 and 10. If `sigma` is an `int`, it is used as a seed to generate it randomly. Otherwise, it needs to be a one-dimensional array-like of length `r`. `sigma` and `rom0` cannot both be not `None`. b Initial right tangential directions. If `None`, if is chosen as all ones. If `b` is an `int`, it is used as a seed to generate it randomly. Otherwise, it needs to be a |VectorArray| of length `r` from `fom.B.source`. `b` and `rom0` cannot both be not `None`. c Initial left tangential directions. If `None`, if is chosen as all ones. If `c` is an `int`, it is used as a seed to generate it randomly. Otherwise, it needs to be a |VectorArray| of length `r` from `fom.Cp.range`. `c` and `rom0` cannot both be not `None`. rom0 Initial reduced order model. If `None`, then `sigma`, `b`, and `c` are used. Otherwise, it needs to be an |LTIModel| of order `r` and it is used to construct `sigma`, `b`, and `c`. tol Tolerance for the convergence criterion. maxit Maximum number of iterations. num_prev Number of previous iterations to compare the current iteration to. Larger number can avoid occasional cyclic behavior of IRKA. force_sigma_in_rhp If `False`, new interpolation are reflections of the current reduced order model's poles. Otherwise, only the poles in the left half-plane are reflected. projection Projection method: - `'orth'`: projection matrices are orthogonalized with respect to the Euclidean inner product - `'biorth'`: projection matrices are biorthogolized with respect to the E product conv_crit Convergence criterion: - `'sigma'`: relative change in interpolation points - `'h2'`: relative :math:`\mathcal{H}_2` distance of reduced-order models compute_errors Should the relative :math:`\mathcal{H}_2`-errors of intermediate reduced order models be computed. .. warning:: Computing :math:`\mathcal{H}_2`-errors is expensive. Use this option only if necessary. irka_options Dict of options for IRKAReductor.reduce. Returns ------- rom Reduced-order |SecondOrderModel|. """ fom = self.fom if not fom.cont_time: raise NotImplementedError assert 0 < r < fom.order assert isinstance(num_prev, int) and num_prev >= 1 assert projection in ('orth', 'biorth') assert conv_crit in ('sigma', 'h2') assert irka_options is None or isinstance(irka_options, dict) if not irka_options: irka_options = {} # initial interpolation points and tangential directions assert sigma is None or isinstance(sigma, int) or len(sigma) == r assert b is None or isinstance(b, int) or b in fom.B.source and len(b) == r assert c is None or isinstance(c, int) or c in fom.Cp.range and len(c) == r assert (rom0 is None or isinstance(rom0, SecondOrderModel) and rom0.order == r and rom0.B.source == fom.B.source and rom0.Cp.range == fom.Cp.range) assert sigma is None or rom0 is None assert b is None or rom0 is None assert c is None or rom0 is None if rom0 is not None: with self.logger.block('Intermediate reduction ...'): irka_reductor = IRKAReductor(rom0.to_lti()) rom_r = irka_reductor.reduce(r, **irka_options) poles, b, c = _poles_and_tangential_directions(rom_r) sigma = np.abs(poles.real) + poles.imag * 1j if force_sigma_in_rhp else -poles else: if sigma is None: sigma = np.logspace(-1, 1, r) elif isinstance(sigma, int): np.random.seed(sigma) sigma = np.abs(np.random.randn(r)) if b is None: b = fom.B.source.ones(r) elif isinstance(b, int): b = fom.B.source.random(r, distribution='normal', seed=b) if c is None: c = fom.Cp.range.ones(r) elif isinstance(c, int): c = fom.Cp.range.random(r, distribution='normal', seed=c) self.logger.info('Starting SOR-IRKA') self.conv_crit = [] self.sigmas = [np.array(sigma)] self.R = [b] self.L = [c] self.errors = [] if compute_errors else None self._pg_reductor = SOBHIReductor(fom) # main loop for it in range(maxit): # interpolatory reduced order model rom = self._pg_reductor.reduce(sigma, b, c, projection=projection) # reduction to a system with r poles with self.logger.block('Intermediate reduction ...'): irka_reductor = IRKAReductor(rom.to_lti()) rom_r = irka_reductor.reduce(r, **irka_options) # new interpolation points and tangential directions poles, b, c = _poles_and_tangential_directions(rom_r) sigma = np.abs(poles.real) + poles.imag * 1j if force_sigma_in_rhp else -poles self.sigmas.append(sigma) self.R.append(b) self.L.append(c) # compute convergence criterion if conv_crit == 'sigma': dist = _convergence_criterion(self.sigmas[:-num_prev-2:-1], conv_crit) self.conv_crit.append(dist) elif conv_crit == 'h2': if it == 0: rom_list = (num_prev + 1) * [None] rom_list[0] = rom self.conv_crit.append(np.inf) else: rom_list[1:] = rom_list[:-1] rom_list[0] = rom dist = _convergence_criterion(rom_list, conv_crit) self.conv_crit.append(dist) # report convergence self.logger.info(f'Convergence criterion in iteration {it + 1}: {self.conv_crit[-1]:e}') if compute_errors: if np.max(rom.poles().real) < 0: err = fom - rom rel_H2_err = err.h2_norm() / fom.h2_norm() else: rel_H2_err = np.inf self.errors.append(rel_H2_err) self.logger.info(f'Relative H2-error in iteration {it + 1}: {rel_H2_err:e}') # check if convergence criterion is satisfied if self.conv_crit[-1] < tol: break # final reduced order model rom = self._pg_reductor.reduce(sigma, b, c, projection=projection) self.V = self._pg_reductor.V self.W = self._pg_reductor.W return rom
def reduce(self, r, sigma=None, b=None, c=None, rom0=None, tol=1e-4, maxit=100, num_prev=1, force_sigma_in_rhp=False, projection='orth', conv_crit='sigma', compute_errors=False, irka_options=None): r"""Reduce using SOR-IRKA. It uses IRKA as the intermediate reductor, to reduce from 2r to r poles. See Section 5.3.2 in [W12]_. Parameters ---------- r Order of the reduced order model. sigma Initial interpolation points (closed under conjugation). If `None`, interpolation points are log-spaced between 0.1 and 10. If `sigma` is an `int`, it is used as a seed to generate it randomly. Otherwise, it needs to be a one-dimensional array-like of length `r`. `sigma` and `rom0` cannot both be not `None`. b Initial right tangential directions. If `None`, if is chosen as all ones. If `b` is an `int`, it is used as a seed to generate it randomly. Otherwise, it needs to be a |VectorArray| of length `r` from `fom.B.source`. `b` and `rom0` cannot both be not `None`. c Initial left tangential directions. If `None`, if is chosen as all ones. If `c` is an `int`, it is used as a seed to generate it randomly. Otherwise, it needs to be a |VectorArray| of length `r` from `fom.Cp.range`. `c` and `rom0` cannot both be not `None`. rom0 Initial reduced order model. If `None`, then `sigma`, `b`, and `c` are used. Otherwise, it needs to be an |LTIModel| of order `r` and it is used to construct `sigma`, `b`, and `c`. tol Tolerance for the convergence criterion. maxit Maximum number of iterations. num_prev Number of previous iterations to compare the current iteration to. Larger number can avoid occasional cyclic behavior of IRKA. force_sigma_in_rhp If `False`, new interpolation are reflections of the current reduced order model's poles. Otherwise, only the poles in the left half-plane are reflected. projection Projection method: - `'orth'`: projection matrices are orthogonalized with respect to the Euclidean inner product - `'biorth'`: projection matrices are biorthogolized with respect to the E product conv_crit Convergence criterion: - `'sigma'`: relative change in interpolation points - `'h2'`: relative :math:`\mathcal{H}_2` distance of reduced-order models compute_errors Should the relative :math:`\mathcal{H}_2`-errors of intermediate reduced order models be computed. .. warning:: Computing :math:`\mathcal{H}_2`-errors is expensive. Use this option only if necessary. irka_options Dict of options for IRKAReductor.reduce. Returns ------- rom Reduced-order |SecondOrderModel|. """ fom = self.fom if not fom.cont_time: raise NotImplementedError assert 0 < r < fom.order assert isinstance(num_prev, int) and num_prev >= 1 assert projection in ('orth', 'biorth') assert conv_crit in ('sigma', 'h2') assert irka_options is None or isinstance(irka_options, dict) if not irka_options: irka_options = {} # initial interpolation points and tangential directions assert sigma is None or isinstance(sigma, int) or len(sigma) == r assert b is None or isinstance( b, int) or b in fom.B.source and len(b) == r assert c is None or isinstance( c, int) or c in fom.Cp.range and len(c) == r assert (rom0 is None or isinstance(rom0, SecondOrderModel) and rom0.order == r and rom0.B.source == fom.B.source and rom0.Cp.range == fom.Cp.range) assert sigma is None or rom0 is None assert b is None or rom0 is None assert c is None or rom0 is None if rom0 is not None: with self.logger.block('Intermediate reduction ...'): irka_reductor = IRKAReductor(rom0.to_lti()) rom_r = irka_reductor.reduce(r, **irka_options) poles, b, c = _poles_and_tangential_directions(rom_r) sigma = np.abs( poles.real) + poles.imag * 1j if force_sigma_in_rhp else -poles else: if sigma is None: sigma = np.logspace(-1, 1, r) elif isinstance(sigma, int): np.random.seed(sigma) sigma = np.abs(np.random.randn(r)) if b is None: b = fom.B.source.ones(r) elif isinstance(b, int): b = fom.B.source.random(r, distribution='normal', seed=b) if c is None: c = fom.Cp.range.ones(r) elif isinstance(c, int): c = fom.Cp.range.random(r, distribution='normal', seed=c) self.logger.info('Starting SOR-IRKA') self.conv_crit = [] self.sigmas = [np.array(sigma)] self.R = [b] self.L = [c] self.errors = [] if compute_errors else None self._pg_reductor = SOBHIReductor(fom) # main loop for it in range(maxit): # interpolatory reduced order model rom = self._pg_reductor.reduce(sigma, b, c, projection=projection) # reduction to a system with r poles with self.logger.block('Intermediate reduction ...'): irka_reductor = IRKAReductor(rom.to_lti()) rom_r = irka_reductor.reduce(r, **irka_options) # new interpolation points and tangential directions poles, b, c = _poles_and_tangential_directions(rom_r) sigma = np.abs( poles.real) + poles.imag * 1j if force_sigma_in_rhp else -poles self.sigmas.append(sigma) self.R.append(b) self.L.append(c) # compute convergence criterion if conv_crit == 'sigma': dist = _convergence_criterion(self.sigmas[:-num_prev - 2:-1], conv_crit) self.conv_crit.append(dist) elif conv_crit == 'h2': if it == 0: rom_list = (num_prev + 1) * [None] rom_list[0] = rom self.conv_crit.append(np.inf) else: rom_list[1:] = rom_list[:-1] rom_list[0] = rom dist = _convergence_criterion(rom_list, conv_crit) self.conv_crit.append(dist) # report convergence self.logger.info( f'Convergence criterion in iteration {it + 1}: {self.conv_crit[-1]:e}' ) if compute_errors: if np.max(rom.poles().real) < 0: err = fom - rom rel_H2_err = err.h2_norm() / fom.h2_norm() else: rel_H2_err = np.inf self.errors.append(rel_H2_err) self.logger.info( f'Relative H2-error in iteration {it + 1}: {rel_H2_err:e}') # check if convergence criterion is satisfied if self.conv_crit[-1] < tol: break # final reduced order model rom = self._pg_reductor.reduce(sigma, b, c, projection=projection) self.V = self._pg_reductor.V self.W = self._pg_reductor.W return rom
def main( diameter: float = Argument( 0.1, help='Diameter option for the domain discretizer.'), r: int = Argument(5, help='Order of the ROMs.'), ): r"""2D heat equation demo. Discretization of the PDE: .. math:: :nowrap: \begin{align*} \partial_t z(x, y, t) &= \Delta z(x, y, t), & 0 < x, y < 1,\ t > 0 \\ -\nabla z(0, y, t) \cdot n &= z(0, y, t) - u(t), & 0 < y < 1, t > 0 \\ -\nabla z(1, y, t) \cdot n &= z(1, y, t), & 0 < y < 1, t > 0 \\ -\nabla z(0, x, t) \cdot n &= z(0, x, t), & 0 < x < 1, t > 0 \\ -\nabla z(1, x, t) \cdot n &= z(1, x, t), & 0 < x < 1, t > 0 \\ z(x, y, 0) &= 0 & 0 < x, y < 1 \\ y(t) &= \int_0^1 z(1, y, t) dy, & t > 0 \\ \end{align*} where :math:`u(t)` is the input and :math:`y(t)` is the output. """ set_log_levels({'pymor.algorithms.gram_schmidt.gram_schmidt': 'WARNING'}) p = InstationaryProblem(StationaryProblem( domain=RectDomain([[0., 0.], [1., 1.]], left='robin', right='robin', top='robin', bottom='robin'), diffusion=ConstantFunction(1., 2), robin_data=(ConstantFunction(1., 2), ExpressionFunction('(x[...,0] < 1e-10) * 1.', 2)), outputs=[('l2_boundary', ExpressionFunction('(x[...,0] > (1 - 1e-10)) * 1.', 2))]), ConstantFunction(0., 2), T=1.) fom, _ = discretize_instationary_cg(p, diameter=diameter, nt=100) fom.visualize(fom.solve()) lti = fom.to_lti() print(f'order of the model = {lti.order}') print(f'number of inputs = {lti.dim_input}') print(f'number of outputs = {lti.dim_output}') # System poles poles = lti.poles() fig, ax = plt.subplots() ax.plot(poles.real, poles.imag, '.') ax.set_title('System poles') plt.show() # Magnitude plot of the full model w = np.logspace(-1, 3, 100) fig, ax = plt.subplots() lti.mag_plot(w, ax=ax) ax.set_title('Magnitude plot of the full model') plt.show() # Hankel singular values hsv = lti.hsv() fig, ax = plt.subplots() ax.semilogy(range(1, len(hsv) + 1), hsv, '.-') ax.set_title('Hankel singular values') plt.show() # Norms of the system print(f'FOM H_2-norm: {lti.h2_norm():e}') if config.HAVE_SLYCOT: print(f'FOM H_inf-norm: {lti.hinf_norm():e}') else: print('Skipped H_inf-norm calculation due to missing slycot.') print(f'FOM Hankel-norm: {lti.hankel_norm():e}') # Model order reduction run_mor_method(lti, w, BTReductor(lti), 'BT', r, tol=1e-5) run_mor_method(lti, w, LQGBTReductor(lti), 'LQGBT', r, tol=1e-5) run_mor_method(lti, w, BRBTReductor(lti), 'BRBT', r, tol=1e-5) run_mor_method(lti, w, IRKAReductor(lti), 'IRKA', r) run_mor_method(lti, w, TSIAReductor(lti), 'TSIA', r) run_mor_method(lti, w, OneSidedIRKAReductor(lti, 'V'), 'OS-IRKA', r)