コード例 #1
0
ファイル: sobt.py プロジェクト: tobiasleibner/pymor
    def reduce(self, r, projection='bfsr'):
        """Reduce using SOBT.

        Parameters
        ----------
        r
            Order of the reduced model.
        projection
            Projection method used:

            - `'sr'`: square root method
            - `'bfsr'`: balancing-free square root method (default, since it avoids scaling by
              singular values and orthogonalizes the projection matrices, which might make it more
              accurate than the square root method)
            - `'biorth'`: like the balancing-free square root method, except it biorthogonalizes the
              projection matrices

        Returns
        -------
        rom
            Reduced-order |SecondOrderModel|.
        """
        assert 0 < r < self.fom.order
        assert projection in ('sr', 'bfsr', 'biorth')

        # compute all necessary Gramian factors
        pcf = self.fom.gramian('pc_lrcf', mu=self.mu)
        pof = self.fom.gramian('po_lrcf', mu=self.mu)
        vcf = self.fom.gramian('vc_lrcf', mu=self.mu)
        vof = self.fom.gramian('vo_lrcf', mu=self.mu)

        if r > min(len(pcf), len(pof), len(vcf), len(vof)):
            raise ValueError(
                'r needs to be smaller than the sizes of Gramian factors.')

        # find necessary SVDs
        Up, sp, Vp = spla.svd(pof.inner(pcf), lapack_driver='gesvd')
        Up = Up.T
        Uv, sv, Vv = spla.svd(vof.inner(vcf, product=self.fom.M),
                              lapack_driver='gesvd')
        Uv = Uv.T

        # compute projection matrices and find the reduced model
        self.V1 = pcf.lincomb(Vp[:r])
        self.W1 = pof.lincomb(Up[:r])
        self.V2 = vcf.lincomb(Vv[:r])
        self.W2 = vof.lincomb(Uv[:r])
        if projection == 'sr':
            alpha1 = 1 / np.sqrt(sp[:r])
            self.V1.scal(alpha1)
            self.W1.scal(alpha1)
            alpha2 = 1 / np.sqrt(sv[:r])
            self.V2.scal(alpha2)
            self.W2.scal(alpha2)
            W1TV1invW1TV2 = self.W1.inner(self.V2)
            projected_ops = {'M': IdentityOperator(NumpyVectorSpace(r))}
        elif projection == 'bfsr':
            gram_schmidt(self.V1, atol=0, rtol=0, copy=False)
            gram_schmidt(self.W1, atol=0, rtol=0, copy=False)
            gram_schmidt(self.V2, atol=0, rtol=0, copy=False)
            gram_schmidt(self.W2, atol=0, rtol=0, copy=False)
            W1TV1invW1TV2 = spla.solve(self.W1.inner(self.V1),
                                       self.W1.inner(self.V2))
            projected_ops = {
                'M': project(self.fom.M,
                             range_basis=self.W2,
                             source_basis=self.V2)
            }
        elif projection == 'biorth':
            gram_schmidt_biorth(self.V1, self.W1, copy=False)
            gram_schmidt_biorth(self.V2,
                                self.W2,
                                product=self.fom.M,
                                copy=False)
            W1TV1invW1TV2 = self.W1.inner(self.V2)
            projected_ops = {'M': IdentityOperator(NumpyVectorSpace(r))}

        projected_ops.update({
            'E':
            project(self.fom.E.assemble(mu=self.mu),
                    range_basis=self.W2,
                    source_basis=self.V2),
            'K':
            project(self.fom.K.assemble(mu=self.mu),
                    range_basis=self.W2,
                    source_basis=self.V1.lincomb(W1TV1invW1TV2.T)),
            'B':
            project(self.fom.B.assemble(mu=self.mu),
                    range_basis=self.W2,
                    source_basis=None),
            'Cp':
            project(self.fom.Cp.assemble(mu=self.mu),
                    range_basis=None,
                    source_basis=self.V1.lincomb(W1TV1invW1TV2.T)),
            'Cv':
            project(self.fom.Cv.assemble(mu=self.mu),
                    range_basis=None,
                    source_basis=self.V2),
            'D':
            self.fom.D.assemble(mu=self.mu),
        })

        rom = SecondOrderModel(name=self.fom.name + '_reduced',
                               **projected_ops)
        rom.disable_logging()
        return rom
コード例 #2
0
 def build_rom(self, projected_operators, error_estimator):
     return SecondOrderModel(error_estimator=error_estimator, **projected_operators)
コード例 #3
0
ファイル: parametric_string.py プロジェクト: meretp/pymor
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.'),
):
    """Parametric string example."""
    set_log_levels({'pymor.algorithms.gram_schmidt.gram_schmidt': 'WARNING'})

    # Assemble M, D, K, B, C_p
    assert n % 2 == 1, 'The order has to be an odd integer.'

    n2 = (n + 1) // 2

    k = 0.01  # stiffness

    M = sps.eye(n, format='csc')
    E = 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
    Mop = NumpyMatrixOperator(M)
    Eop = NumpyMatrixOperator(E) * ProjectionParameterFunctional('damping')
    Kop = NumpyMatrixOperator(K)
    Bop = NumpyMatrixOperator(B)
    Cpop = NumpyMatrixOperator(Cp)

    so_sys = SecondOrderModel(Mop, Eop, Kop, Bop, Cpop)

    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}')

    mu_list = [1, 5, 10]
    w = np.logspace(-3, 2, 200)

    # System poles
    fig, ax = plt.subplots()
    for mu in mu_list:
        poles = so_sys.poles(mu=mu)
        ax.plot(poles.real, poles.imag, '.', label=fr'$\mu = {mu}$')
    ax.set_title('System poles')
    ax.legend()
    plt.show()

    # Magnitude plots
    fig, ax = plt.subplots()
    for mu in mu_list:
        so_sys.mag_plot(w, ax=ax, mu=mu, label=fr'$\mu = {mu}$')
    ax.set_title('Magnitude plot of the full model')
    ax.legend()
    plt.show()

    # "Hankel" singular values
    fig, ax = plt.subplots(2,
                           2,
                           figsize=(12, 8),
                           sharey=True,
                           constrained_layout=True)
    for mu in mu_list:
        psv = so_sys.psv(mu=mu)
        vsv = so_sys.vsv(mu=mu)
        pvsv = so_sys.pvsv(mu=mu)
        vpsv = so_sys.vpsv(mu=mu)
        ax[0, 0].semilogy(range(1,
                                len(psv) + 1),
                          psv,
                          '.-',
                          label=fr'$\mu = {mu}$')
        ax[0, 1].semilogy(range(1, len(vsv) + 1), vsv, '.-')
        ax[1, 0].semilogy(range(1, len(pvsv) + 1), pvsv, '.-')
        ax[1, 1].semilogy(range(1, len(vpsv) + 1), vpsv, '.-')
    ax[0, 0].set_title('Position singular values')
    ax[0, 1].set_title('Velocity singular values')
    ax[1, 0].set_title('Position-velocity singular values')
    ax[1, 1].set_title('Velocity-position singular values')
    fig.legend(loc='upper center', ncol=len(mu_list))
    plt.show()

    # System norms
    for mu in mu_list:
        print(f'mu = {mu}:')
        print(f'    H_2-norm of the full model:    {so_sys.h2_norm(mu=mu):e}')
        if config.HAVE_SLYCOT:
            print(
                f'    H_inf-norm of the full model:  {so_sys.hinf_norm(mu=mu):e}'
            )
        print(
            f'    Hankel-norm of the full model: {so_sys.hankel_norm(mu=mu):e}'
        )

    # Model order reduction
    run_mor_method_param(so_sys, r, w, mu_list, SOBTpReductor, 'SOBTp')
    run_mor_method_param(so_sys, r, w, mu_list, SOBTvReductor, 'SOBTv')
    run_mor_method_param(so_sys, r, w, mu_list, SOBTpvReductor, 'SOBTpv')
    run_mor_method_param(so_sys, r, w, mu_list, SOBTvpReductor, 'SOBTvp')
    run_mor_method_param(so_sys, r, w, mu_list, SOBTfvReductor, 'SOBTfv')
    run_mor_method_param(so_sys, r, w, mu_list, SOBTReductor, 'SOBT')
    run_mor_method_param(so_sys, r, w, mu_list, SORIRKAReductor, 'SOR-IRKA')
    run_mor_method_param(so_sys.to_lti(), r, w, mu_list, BTReductor, 'BT')
    run_mor_method_param(so_sys.to_lti(), r, w, mu_list, IRKAReductor, 'IRKA')