示例#1
0
    def reduce(self):
        if self.residual_range is not False:
            with self.logger.block('Estimating residual range ...'):
                try:
                    self.residual_range, self.residual_range_dims = \
                        estimate_image_hierarchical([self.operator], [self.rhs],
                                                    self.RB,
                                                    (self.residual_range, self.residual_range_dims),
                                                    orthonormalize=True, product=self.product,
                                                    riesz_representatives=self.riesz_representatives)
                except ImageCollectionError as e:
                    self.logger.warning(f'Cannot compute range of {e.op}. Evaluation will be slow.')
                    self.residual_range = False

        if self.residual_range is False:
            operator = project(self.operator, None, self.RB)
            return NonProjectedResidualOperator(operator, self.rhs, self.riesz_representatives, self.product)

        with self.logger.block('Projecting residual operator ...'):
            if self.riesz_representatives:
                operator = project(self.operator, self.residual_range, self.RB, product=None)  # the product cancels out.
                rhs = project(self.rhs, self.residual_range, None, product=None)
            else:
                operator = project(self.operator, self.residual_range, self.RB, product=self.product)
                rhs = project(self.rhs, self.residual_range, None, product=self.product)

        return ResidualOperator(operator, rhs)
示例#2
0
def test_project_to_subbasis(operator_with_arrays):
    op, mu, U, V = operator_with_arrays
    op_UV = project(op, V, U)
    np.random.seed(4711 + U.dim + len(V))

    for dim_range in {None, 0, len(V) // 2, len(V)}:
        for dim_source in {None, 0, len(U) // 2, len(U)}:
            op_UV_sb = project_to_subbasis(op_UV, dim_range, dim_source)

            assert op_UV_sb.range.dim == (op_UV.range.dim
                                          if dim_range is None else dim_range)
            assert op_UV_sb.source.dim == (op_UV.source.dim if
                                           dim_source is None else dim_source)

            range_basis = V if dim_range is None else V[:dim_range]
            source_basis = U if dim_source is None else U[:dim_source]

            op_UV_sb2 = project(op, range_basis, source_basis)

            u = op_UV_sb2.source.make_array(np.random.random(
                len(source_basis)))

            assert np.all(
                almost_equal(op_UV_sb.apply(u, mu=mu), op_UV_sb2.apply(u,
                                                                       mu=mu)))
示例#3
0
文件: residual.py 项目: pymor/pymor
    def reduce(self):
        if self.residual_range is not False:
            with self.logger.block('Estimating residual range ...'):
                try:
                    self.residual_range, self.residual_range_dims = \
                        estimate_image_hierarchical([self.operator, self.mass], [self.rhs],
                                                    self.RB,
                                                    (self.residual_range, self.residual_range_dims),
                                                    orthonormalize=True, product=self.product,
                                                    riesz_representatives=True)
                except ImageCollectionError as e:
                    self.logger.warning(f'Cannot compute range of {e.op}. Evaluation will be slow.')
                    self.residual_range = False

        if self.residual_range is False:
            operator = project(self.operator, None, self.RB)
            mass = project(self.mass, None, self.RB)
            return NonProjectedImplicitEulerResidualOperator(operator, mass, self.rhs, self.dt, self.product)

        with self.logger.block('Projecting residual operator ...'):
            operator = project(self.operator, self.residual_range, self.RB, product=None)  # the product always cancels out.
            mass = project(self.mass, self.residual_range, self.RB, product=None)
            rhs = project(self.rhs, self.residual_range, None, product=None)

        return ImplicitEulerResidualOperator(operator, mass, rhs, self.dt)
示例#4
0
    def reduce(self):
        if self.residual_range is not False:
            with self.logger.block('Estimating residual range ...'):
                try:
                    self.residual_range, self.residual_range_dims = \
                        estimate_image_hierarchical([self.operator], [self.rhs],
                                                    self.RB,
                                                    (self.residual_range, self.residual_range_dims),
                                                    orthonormalize=True, product=self.product,
                                                    riesz_representatives=self.riesz_representatives)
                except ImageCollectionError as e:
                    self.logger.warning('Cannot compute range of {}. Evaluation will be slow.'.format(e.op))
                    self.residual_range = False

        if self.residual_range is False:
            operator = project(self.operator, None, self.RB)
            return NonProjectedResidualOperator(operator, self.rhs, self.riesz_representatives, self.product)

        with self.logger.block('Projecting residual operator ...'):
            if self.riesz_representatives:
                operator = project(self.operator, self.residual_range, self.RB, product=None)  # the product cancels out.
                rhs = project(self.rhs, self.residual_range, None, product=None)
            else:
                operator = project(self.operator, self.residual_range, self.RB, product=self.product)
                rhs = project(self.rhs, self.residual_range, None, product=self.product)

        return ResidualOperator(operator, rhs)
示例#5
0
    def reduce(self):
        if self.residual_range is not False:
            with self.logger.block('Estimating residual range ...'):
                try:
                    self.residual_range, self.residual_range_dims = \
                        estimate_image_hierarchical([self.operator, self.mass], [self.functional.T],
                                                    self.RB,
                                                    (self.residual_range, self.residual_range_dims),
                                                    orthonormalize=True, product=self.product,
                                                    riesz_representatives=True)
                except ImageCollectionError as e:
                    self.logger.warning('Cannot compute range of {}. Evaluation will be slow.'.format(e.op))
                    self.residual_range = False

        if self.residual_range is False:
            operator = project(self.operator, None, self.RB)
            mass = project(self.mass, None, self.RB)
            return NonProjectedImplicitEulerResidualOperator(operator, mass, self.functional, self.dt, self.product)

        with self.logger.block('Projecting residual operator ...'):
            operator = project(self.operator, self.residual_range, self.RB, product=None)  # the product always cancels out.
            mass = project(self.mass, self.residual_range, self.RB, product=None)
            functional = project(self.functional, None, self.residual_range, product=None)

        return ImplicitEulerResidualOperator(operator, mass, functional, self.dt)
示例#6
0
 def project_operators(self):
     fom = self.fom
     RB = self.bases['RB']
     projected_operators = {'operator': project(fom.operator, RB, RB),
                            'rhs':      project(fom.rhs, RB, None),
                            'products': {k: project(v, RB, RB) for k, v in fom.products.items()},
                            'outputs':  {k: project(v, None, RB) for k, v in fom.outputs.items()}}
     return projected_operators
示例#7
0
文件: basic.py 项目: pymor/pymor
 def project_operators(self):
     fom = self.fom
     RB = self.bases['RB']
     projected_operators = {'operator': project(fom.operator, RB, RB),
                            'rhs':      project(fom.rhs, RB, None),
                            'products': {k: project(v, RB, RB) for k, v in fom.products.items()},
                            'outputs':  {k: project(v, None, RB) for k, v in fom.outputs.items()}}
     return projected_operators
示例#8
0
 def project_operators(self):
     fom = self.fom
     W = self.bases['W']
     V = self.bases['V']
     projected_operators = {'A': project(fom.A, W, V),
                            'B': project(fom.B, W, None),
                            'C': project(fom.C, None, V),
                            'D': fom.D,
                            'E': None if self.E_biorthonormal else project(fom.E, W, V)}
     return projected_operators
示例#9
0
文件: basic.py 项目: pymor/pymor
 def project_operators(self):
     fom = self.fom
     W = self.bases['W']
     V = self.bases['V']
     projected_operators = {'A': project(fom.A, W, V),
                            'B': project(fom.B, W, None),
                            'C': project(fom.C, None, V),
                            'D': fom.D,
                            'E': None if self.E_biorthonormal else project(fom.E, W, V)}
     return projected_operators
示例#10
0
    def project_output(self):
        output_functional = self.fom.output_functional_dict
        li_part = output_functional['linear_part']
        bi_part = output_functional['bilinear_part']
        d_u_li_part = output_functional['d_u_linear_part']
        d_u_bi_part = output_functional['d_u_bilinear_part']

        RB = self.RBPrimal
        projected_functionals = {
            'output_coefficient':
            output_functional['output_coefficient'],
            'linear_part':
            project(li_part, RB, None),
            'bilinear_part':
            project(bi_part, RB, RB),
            'd_u_linear_part':
            project(d_u_li_part, RB, None),
            'd_u_bilinear_part':
            project(d_u_bi_part, RB, RB),
            'dual_projected_d_u_bilinear_part':
            project(d_u_bi_part, RB, self.RBDual),
            'primal_dual_projected_op':
            project(self.fom.primal_model.operator, RB, self.RBDual),
            'dual_projected_rhs':
            project(self.fom.primal_model.rhs, self.RBDual, None),
            'primal_projected_dual_rhs':
            project(self.dual_intermediate_fom.rhs, RB, None),
        }
        return projected_functionals
示例#11
0
文件: operators.py 项目: pymor/pymor
def test_project_with_product_2(operator_with_arrays_and_products):
    op, mu, U, V, sp, rp = operator_with_arrays_and_products
    op_U = project(op, None, U)
    op_V = project(op, V, None, product=rp)
    op_U_V = project(op_U, V, None, product=rp)
    op_V_U = project(op_V, None, U)
    op_UV = project(op, V, U, product=rp)
    np.random.seed(4711 + U.dim + len(V))
    W = op_UV.source.make_array(np.random.random(len(U)))
    Y0 = op_UV.apply(W, mu=mu)
    Y1 = op_U_V.apply(W, mu=mu)
    Y2 = op_V_U.apply(W, mu=mu)
    assert np.all(almost_equal(Y0, Y1))
    assert np.all(almost_equal(Y0, Y2))
示例#12
0
def test_project_with_product_2(operator_with_arrays_and_products):
    op, mu, U, V, sp, rp = operator_with_arrays_and_products
    op_U = project(op, None, U)
    op_V = project(op, V, None, product=rp)
    op_U_V = project(op_U, V, None, product=rp)
    op_V_U = project(op_V, None, U)
    op_UV = project(op, V, U, product=rp)
    np.random.seed(4711 + U.dim + len(V))
    W = op_UV.source.make_array(np.random.random(len(U)))
    Y0 = op_UV.apply(W, mu=mu)
    Y1 = op_U_V.apply(W, mu=mu)
    Y2 = op_V_U.apply(W, mu=mu)
    assert np.all(almost_equal(Y0, Y1))
    assert np.all(almost_equal(Y0, Y2))
示例#13
0
def test_lincomb_op():
    p1 = MonomOperator(1)
    p2 = MonomOperator(2)
    p12 = p1 + p2
    p0 = p1 - p1
    x = np.linspace(-1., 1., num=3)
    vx = p1.source.make_array((x[:, np.newaxis]))
    one = p1.source.make_array([1])
    assert np.allclose(p0.apply(vx).to_numpy(), [0.])
    assert np.allclose(p12.apply(vx).to_numpy(), (x * x + x)[:, np.newaxis])
    assert np.allclose((p1 * 2.).apply(vx).to_numpy(), (x * 2.)[:, np.newaxis])
    with pytest.raises(AssertionError):
        p2.jacobian(vx)
    for i in range(len(vx)):
        assert almost_equal(
            p2.jacobian(vx[i]).apply(one),
            p1.apply(vx[i]) * 2.)
        assert almost_equal(p0.jacobian(vx[i]).apply(one), vx[i] * 0.)
    with pytest.raises(TypeError):
        p2.as_vector()
    p1.as_vector()
    assert almost_equal(p1.as_vector(), p1.apply(p1.source.make_array([1.])))

    basis = p1.source.make_array([1.])
    for p in (p1, p2, p12):
        projected = project(p, basis, basis)
        pa = projected.apply(vx)
        assert almost_equal(pa, p.apply(vx)).all()
示例#14
0
def test_project_with_product(operator_with_arrays_and_products):
    op, mu, U, V, sp, rp = operator_with_arrays_and_products
    op_UV = project(op, V, U, product=rp)
    np.random.seed(4711 + U.dim + len(V))
    coeffs = np.random.random(len(U))
    X = op_UV.apply(op_UV.source.make_array(coeffs), mu=mu)
    Y = op_UV.range.make_array(rp.apply2(op.apply(U.lincomb(coeffs), mu=mu), V))
    assert np.all(almost_equal(X, Y))
示例#15
0
文件: operators.py 项目: pymor/pymor
def test_project_with_product(operator_with_arrays_and_products):
    op, mu, U, V, sp, rp = operator_with_arrays_and_products
    op_UV = project(op, V, U, product=rp)
    np.random.seed(4711 + U.dim + len(V))
    coeffs = np.random.random(len(U))
    X = op_UV.apply(op_UV.source.make_array(coeffs), mu=mu)
    Y = op_UV.range.make_array(rp.apply2(op.apply(U.lincomb(coeffs), mu=mu), V))
    assert np.all(almost_equal(X, Y))
示例#16
0
文件: operators.py 项目: pymor/pymor
def test_project(operator_with_arrays):
    op, mu, U, V = operator_with_arrays
    op_UV = project(op, V, U)
    np.random.seed(4711 + U.dim + len(V))
    coeffs = np.random.random(len(U))
    X = op_UV.apply(op_UV.source.make_array(coeffs), mu=mu)
    Y = op_UV.range.make_array(V.dot(op.apply(U.lincomb(coeffs), mu=mu)).T)
    assert np.all(almost_equal(X, Y))
示例#17
0
def test_project(operator_with_arrays):
    op, mu, U, V = operator_with_arrays
    op_UV = project(op, V, U)
    np.random.seed(4711 + U.dim + len(V))
    coeffs = np.random.random(len(U))
    X = op_UV.apply(op_UV.source.make_array(coeffs), mu=mu)
    Y = op_UV.range.make_array(V.dot(op.apply(U.lincomb(coeffs), mu=mu)).T)
    assert np.all(almost_equal(X, Y))
示例#18
0
文件: basic.py 项目: pymor/pymor
    def project_operators(self):
        fom = self.fom
        RB = self.bases['RB']
        product = self.products['RB']

        if self.initial_data_product != product:
            # TODO there should be functionality for this somewhere else
            projection_matrix = RB.gramian(self.initial_data_product)
            projection_op = NumpyMatrixOperator(projection_matrix)
            inverse_projection_op = InverseOperator(projection_op, 'inverse_projection_op')
            pid = project(fom.initial_data, range_basis=RB, source_basis=None, product=self.initial_data_product)
            projected_initial_data = Concatenation([inverse_projection_op, pid])
        else:
            projected_initial_data = project(fom.initial_data, range_basis=RB, source_basis=None,
                                             product=product)

        projected_operators = {'mass':         (None if fom.mass is None or self.product_is_mass else
                                                project(fom.mass, RB, RB)),
                               'operator':     project(fom.operator, RB, RB),
                               'rhs':          project(fom.rhs, RB, None) if fom.rhs is not None else None,
                               'initial_data': projected_initial_data,
                               'products':     {k: project(v, RB, RB) for k, v in fom.products.items()},
                               'outputs':      {k: project(v, None, RB) for k, v in fom.outputs.items()}}

        return projected_operators
示例#19
0
    def project_operators(self):
        fom = self.fom
        RB = self.bases['RB']
        product = self.products['RB']

        if self.initial_data_product != product:
            # TODO there should be functionality for this somewhere else
            projection_matrix = RB.gramian(self.initial_data_product)
            projection_op = NumpyMatrixOperator(projection_matrix)
            inverse_projection_op = InverseOperator(projection_op, 'inverse_projection_op')
            pid = project(fom.initial_data, range_basis=RB, source_basis=None, product=self.initial_data_product)
            projected_initial_data = ConcatenationOperator([inverse_projection_op, pid])
        else:
            projected_initial_data = project(fom.initial_data, range_basis=RB, source_basis=None,
                                             product=product)

        projected_operators = {
            'mass':              (None if (isinstance(fom.mass, IdentityOperator) and product is None
                                           or self.product_is_mass) else
                                  project(fom.mass, RB, RB)),
            'operator':          project(fom.operator, RB, RB),
            'rhs':               project(fom.rhs, RB, None),
            'initial_data':      projected_initial_data,
            'products':          {k: project(v, RB, RB) for k, v in fom.products.items()},
            'output_functional': project(fom.output_functional, None, RB) if fom.output_functional else None
        }

        return projected_operators
示例#20
0
def test_project_to_subbasis_no_source_basis(operator_with_arrays):
    op, mu, U, V = operator_with_arrays
    op_V = project(op, V, None)
    np.random.seed(4711 + U.dim + len(V))

    for dim_range in {None, 0, len(V) // 2, len(V)}:
        op_V_sb = project_to_subbasis(op_V, dim_range, None)

        assert op_V_sb.range.dim == (op_V.range.dim
                                     if dim_range is None else dim_range)
        assert op_V_sb.source == op_V.source

        range_basis = V if dim_range is None else V[:dim_range]

        op_V_sb2 = project(op, range_basis, None)

        assert np.all(
            almost_equal(op_V_sb.apply(U, mu=mu), op_V_sb2.apply(U, mu=mu)))
示例#21
0
文件: basic.py 项目: deneick/pymor
 def assemble(self, mu=None):
     op = self.operator.assemble(mu=mu)
     if op == self.operator:  # avoid infinite recursion in apply_inverse default impl
         return self
     from pymor.algorithms.projection import project
     pop = project(op, range_basis=self.range_basis, source_basis=self.source_basis,
                   product=self.product)
     if self.solver_options:
         pop = pop.with_(solver_options=self.solver_options)
     return pop
示例#22
0
 def project_hessian(self):
     RBP = self.RBPrimal
     RBD = self.RBDual
     fom = self.fom.primal_model
     output_functional = self.fom.output_functional_dict
     linear_part = output_functional['d_u_linear_part']
     bilinear_part = output_functional['d_u_bilinear_part']
     projected_hessian = {}
     for (key, size) in sorted(self.primal_fom.parameters.items()):
         hessian = np.empty(size, dtype=dict)
         for l in range(size):
             D_rhs = project(fom.rhs.d_mu(key, l), RBD, None)
             P_D_op = project(fom.operator.d_mu(key, l), RBP, RBD)
             proj_hessian = {
                 'D_rhs': D_rhs,
                 'P_D_op': PD_op,
             }
             hessian[l] = proj_hessian
         projected_hessian[key] = hessian
     return projected_hessian
示例#23
0
    def reduce(self):
        # Note that it is possible that rhs.source == rhs.range, nameley if both
        # are one-dimensional NumpyVectorSpaces which agree with the range of
        # operator. Usually, this should not happen, since at least one of these
        # spaces should have an id which is different from the id of operator.range.
        # However, even if it happens but rhs is actually a vector, we are on
        # the safe side, since first computing the Riesz representatives does not
        # change anything in one-dimensional spaces, and it does not matter whether
        # we project from the left or from the right.
        rhs_is_functional = (self.rhs.source == self.operator.range)

        if self.residual_range is not False:
            with self.logger.block('Estimating residual range ...'):
                try:
                    self.residual_range, self.residual_range_dims = \
                        estimate_image_hierarchical([self.operator], [self.rhs.T if rhs_is_functional else self.rhs],
                                                    self.RB,
                                                    (self.residual_range, self.residual_range_dims),
                                                    orthonormalize=True, product=self.product,
                                                    riesz_representatives=rhs_is_functional)
                except ImageCollectionError as e:
                    self.logger.warning('Cannot compute range of {}. Evaluation will be slow.'.format(e.op))
                    self.residual_range = False

        if self.residual_range is False:
            operator = project(self.operator, None, self.RB)
            return NonProjectedResidualOperator(operator, self.rhs, rhs_is_functional, self.product)

        with self.logger.block('Projecting residual operator ...'):
            if rhs_is_functional:
                operator = project(self.operator, self.residual_range, self.RB, product=None)  # the product cancels out.
                rhs = project(self.rhs, None, self.residual_range, product=None)
            else:
                operator = project(self.operator, self.residual_range, self.RB, product=self.product)
                rhs = project(self.rhs, self.residual_range, None, product=self.product)

        return ResidualOperator(operator, rhs, rhs_is_functional)
示例#24
0
文件: basic.py 项目: deneick/pymor
 def jacobian(self, U, mu=None):
     if self.linear:
         return self.assemble(mu)
     assert len(U) == 1
     mu = self.parse_parameter(mu)
     if self.source_basis is None:
         J = self.operator.jacobian(U, mu=mu)
     else:
         J = self.operator.jacobian(self.source_basis.lincomb(U.to_numpy()), mu=mu)
     from pymor.algorithms.projection import project
     pop = project(J, range_basis=self.range_basis, source_basis=self.source_basis,
                   product=self.product, name=self.name + '_jacobian')
     if self.solver_options:
         options = self.solver_options.get('jacobian')
         if options:
             pop = pop.with_(solver_options=options)
     return pop
示例#25
0
 def project_operators(self):
     fom = self.fom
     W = self.bases['W']
     V = self.bases['V']
     projected_operators = {'M':  None if self.M_biorthonormal else project(fom.M, W, V),
                            'E':  project(fom.E, W, V),
                            'K':  project(fom.K, W, V),
                            'B':  project(fom.B, W, None),
                            'Cp': project(fom.Cp, None, V),
                            'Cv': project(fom.Cv, None, V),
                            'D':  fom.D}
     return projected_operators
示例#26
0
文件: basic.py 项目: pymor/pymor
 def project_operators(self):
     fom = self.fom
     W = self.bases['W']
     V = self.bases['V']
     projected_operators = {'M':  None if self.M_biorthonormal else project(fom.M, W, V),
                            'E':  project(fom.E, W, V),
                            'K':  project(fom.K, W, V),
                            'B':  project(fom.B, W, None),
                            'Cp': project(fom.Cp, None, V),
                            'Cv': project(fom.Cv, None, V),
                            'D':  fom.D}
     return projected_operators
示例#27
0
文件: operators.py 项目: pymor/pymor
def test_lincomb_op():
    p1 = MonomOperator(1)
    p2 = MonomOperator(2)
    p12 = p1 + p2
    p0 = p1 - p1
    x = np.linspace(-1., 1., num=3)
    vx = p1.source.make_array((x[:, np.newaxis]))
    assert np.allclose(p0.apply(vx).to_numpy(), [0.])
    assert np.allclose(p12.apply(vx).to_numpy(), (x * x + x)[:, np.newaxis])
    assert np.allclose((p1 * 2.).apply(vx).to_numpy(), (x * 2.)[:, np.newaxis])
    assert almost_equal(p2.jacobian(vx).apply(vx), p1.apply(vx) * 2.).all()
    assert almost_equal(p0.jacobian(vx).apply(vx), vx * 0.).all()
    with pytest.raises(TypeError):
        p2.as_vector()
    p1.as_vector()
    assert almost_equal(p1.as_vector(), p1.apply(p1.source.make_array([1.])))

    basis = p1.source.make_array([1.])
    for p in (p1, p2, p12):
        projected = project(p, basis, basis)
        pa = projected.apply(vx)
        assert almost_equal(pa, p.apply(vx)).all()
示例#28
0
文件: basic.py 项目: renemilk/pyMor
 def project_operator(k, op):
     return project(op,
                    range_basis=RB if RB in op.range else None,
                    source_basis=RB if RB in op.source else None,
                    product=self.product if k in self.orthogonal_projection else None)
示例#29
0
    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
示例#30
0
 def project_operator(k, op):
     return project(op,
                    range_basis=RB if RB in op.range else None,
                    source_basis=RB if RB in op.source else None,
                    product=self.product
                    if k in self.orthogonal_projection else None)
示例#31
0
 def project_product(self):
     projected_product = project(self.opt_product, self.RBPrimal,
                                 self.RBPrimal)
     return projected_product
示例#32
0
    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
        -------
        rd
            Reduced system.
        """
        assert 0 < r < self.d.n
        assert projection in ('sr', 'bfsr', 'biorth')

        # compute all necessary Gramian factors
        pcf = self.d.gramian('pcf')
        pof = self.d.gramian('pof')
        vcf = self.d.gramian('vcf')
        vof = self.d.gramian('vof')

        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.d.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, self.d.state_space.id))}
        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.d.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.d.M)
            W1TV1invW1TV2 = self.W1.inner(self.V2)
            projected_ops = {'M': IdentityOperator(NumpyVectorSpace(r, self.d.state_space.id))}

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

        rd = self.d.with_(operators=projected_ops,
                          visualizer=None, estimator=None,
                          cache_region=None, name=self.d.name + '_reduced')
        rd.disable_logging()

        return rd