예제 #1
0
    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.input_dim}')
    print(f'number of outputs  = {so_sys.output_dim}')

    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')
예제 #2
0
 def build_rom(self, projected_operators, error_estimator):
     return SecondOrderModel(error_estimator=error_estimator, **projected_operators)
예제 #3
0
    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.input_dim}')
    print(f'number of outputs  = {so_sys.output_dim}')

    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('Bode plot of the full model')
예제 #4
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
예제 #5
0
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)
예제 #6
0
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')
예제 #7
0
파일: sobt.py 프로젝트: pymor/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')
        pof = self.fom.gramian('po_lrcf')
        vcf = self.fom.gramian('vc_lrcf')
        vof = self.fom.gramian('vo_lrcf')

        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))
        Up = Up.T
        Uv, sv, Vv = spla.svd(vof.inner(vcf, product=self.fom.M))
        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':
            self.V1 = gram_schmidt(self.V1, atol=0, rtol=0)
            self.W1 = gram_schmidt(self.W1, atol=0, rtol=0)
            self.V2 = gram_schmidt(self.V2, atol=0, rtol=0)
            self.W2 = gram_schmidt(self.W2, atol=0, rtol=0)
            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':
            self.V1, self.W1 = gram_schmidt_biorth(self.V1, self.W1)
            self.V2, self.W2 = gram_schmidt_biorth(self.V2, self.W2, product=self.fom.M)
            W1TV1invW1TV2 = self.W1.inner(self.V2)
            projected_ops = {'M': IdentityOperator(NumpyVectorSpace(r))}

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

        rom = SecondOrderModel(name=self.fom.name + '_reduced', **projected_ops)
        rom.disable_logging()
        return rom