Beispiel #1
0
def project_operator(operator, source_basis, range_basis, product=None, name=None):
    '''Project operators to subspaces.

    Replaces `Operators` by `ProjectedOperators` and `LinearOperators`
    by `ProjectedLinearOperators`.
    Moreover, `LinearAffinelyDecomposedOperators` are projected by recursively
    projecting each of its components.

    See also `ProjectedOperator`.

    Parameters
    ----------
    operator
        The `Operator` to project.
    source_basis
        The b_1, ..., b_N as a 2d-array.
    range_basis
        The c_1, ..., c_M as a 2d-array.
    product
        Either an 2d-array or a `Operator` representing the scalar product.
        If None, the euclidean product is chosen.
    name
        Name of the projected operator.
    '''

    name = name or '{}_projected'.format(operator.name)

    if isinstance(operator, LinearAffinelyDecomposedOperator):
        proj_operators = tuple(project_operator(op, source_basis, range_basis, product,
                                                name='{}_projected'.format(op.name))
                               for op in operator.operators)
        if operator.operator_affine_part is not None:
            proj_operator_ap = project_operator(operator.operator_affine_part, source_basis, range_basis, product,
                                                name='{}_projected'.format(operator.operator_affine_part.name))
        else:
            proj_operator_ap = None
        proj_operator = LinearAffinelyDecomposedOperator(proj_operators, proj_operator_ap, operator.functionals, name)
        proj_operator.rename_parameter(operator.parameter_name_map)
        return proj_operator

    elif isinstance(operator, LinearOperatorInterface):
        return ProjectedLinearOperator(operator, source_basis, range_basis, product, name)
    else:
        return ProjectedOperator(operator, source_basis, range_basis, product, name)
Beispiel #2
0
def discretize_elliptic_cg(analytical_problem, diameter=None, domain_discretizer=None,
                           grid=None, boundary_info=None):
    '''Discretize an `EllipticProblem` using finite elements.

    Since operators are not assembled during instatiation, calling this function is
    cheap if the domain discretization proceeds quickly.

    Parameters
    ----------
    analytical_problem
        The `EllipticProblem` to discretize.
    diameter
        If not None, is passed to the domain_discretizer.
    domain_discretizer
        Discretizer to be used for discretizing the analytical domain. This has
        to be function `domain_discretizer(domain_description, diameter=...)`.
        If further arguments should be passed to the discretizer, use
        functools.partial. If None, `discretize_domain_default` is used.
    grid
        Instead of using a domain discretizer, the grid can be passed directly.
    boundary_info
        A `BoundaryInfo` specifying the boundary types of the grid boundary
        entities. Must be provided is `grid` is provided.

    Returns
    -------
    discretization
        The discretization that has been generated.
    data
        Dict with the following entries:
            grid
                The generated grid.
            boundary_info
                The generated `BoundaryInfo`.
    '''

    assert isinstance(analytical_problem, EllipticProblem)
    assert grid is None or boundary_info is not None
    assert boundary_info is None or grid is not None
    assert grid is None or domain_discretizer is None

    if grid is None:
        domain_discretizer = domain_discretizer or discretize_domain_default
        if diameter is None:
            grid, boundary_info = domain_discretizer(analytical_problem.domain)
        else:
            grid, boundary_info = domain_discretizer(analytical_problem.domain, diameter=diameter)

    assert isinstance(grid, (OnedGrid, TriaGrid))

    Operator = DiffusionOperatorP1
    Functional = L2ProductFunctionalP1
    p = analytical_problem

    if p.diffusion_functionals is not None or len(p.diffusion_functions) > 1:
        L0 = Operator(grid, boundary_info, diffusion_constant=0, name='diffusion_boundary_part')

        Li = tuple(Operator(grid, boundary_info, diffusion_function=df, dirichlet_clear_diag=True,
                            name='diffusion_{}'.format(i))
                   for i, df in enumerate(p.diffusion_functions))

        if p.diffusion_functionals is None:
            L = LinearAffinelyDecomposedOperator(Li, L0, name='diffusion')
            L.rename_parameter({'.coefficients': '.diffusion_coefficients'})
        else:
            L = LinearAffinelyDecomposedOperator(Li, L0, p.diffusion_functionals, name='diffusion')
    else:
        L = Operator(grid, boundary_info, diffusion_function=p.diffusion_functions[0],
                     name='diffusion')

    F = Functional(grid, p.rhs, boundary_info, dirichlet_data=p.dirichlet_data)

    import matplotlib.pyplot as pl
    if isinstance(grid, TriaGrid):
        def visualize(U):
            assert len(U) == 1
            pl.tripcolor(grid.centers(2)[:, 0], grid.centers(2)[:, 1], grid.subentities(0, 2), U.data.ravel())
            pl.colorbar()
            pl.show()
    else:
        def visualize(U):
            assert len(U) == 1
            pl.plot(grid.centers(1), U.data.ravel())
            pl.show()
            pass

    discretization = StationaryLinearDiscretization(L, F, visualizer=visualize, name='{}_CG'.format(p.name))

    discretization.h1_product = Operator(grid, boundary_info)
    discretization.h1_norm = induced_norm(discretization.h1_product)
    discretization.l2_product = L2ProductP1(grid, boundary_info)

    if hasattr(p, 'parameter_space'):
        discretization.parameter_space = p.parameter_space

    return discretization, {'grid': grid, 'boundary_info': boundary_info}