Exemple #1
0
def connection_from_dds(places, from_dd, to_dd):
    """
    :arg places: a :class:`~pytential.symbolic.execution.GeometryCollection`
        or an argument taken by its constructor.
    :arg from_dd: a descriptor for the incoming degrees of freedom. This
        can be a :class:`~pytential.symbolic.primitives.DOFDescriptor`
        or an identifier that can be transformed into one by
        :func:`~pytential.symbolic.primitives.as_dofdesc`.
    :arg to_dd: a descriptor for the outgoing degrees of freedom.

    :return: a :class:`DOFConnection` transporting between the two
        kinds of DOF vectors.
    """

    from pytential import sym
    from_dd = sym.as_dofdesc(from_dd)
    to_dd = sym.as_dofdesc(to_dd)

    from pytential import GeometryCollection
    if not isinstance(places, GeometryCollection):
        places = GeometryCollection(places)

    lpot = places.get_geometry(from_dd.geometry)
    from_discr = places.get_discretization(from_dd.geometry,
                                           from_dd.discr_stage)
    to_discr = places.get_discretization(to_dd.geometry, to_dd.discr_stage)

    if from_dd.geometry != to_dd.geometry:
        raise ValueError("cannot interpolate between different geometries")

    if from_dd.granularity is not sym.GRANULARITY_NODE:
        raise ValueError("can only interpolate from `GRANULARITY_NODE`")

    connections = []
    if from_dd.discr_stage is not to_dd.discr_stage:
        from pytential.qbx import QBXLayerPotentialSource
        if not isinstance(lpot, QBXLayerPotentialSource):
            raise ValueError("can only interpolate on a "
                             "`QBXLayerPotentialSource`")

        if to_dd.discr_stage is not sym.QBX_SOURCE_QUAD_STAGE2:
            # TODO: can probably extend this to project from a QUAD_STAGE2
            # using L2ProjectionInverseDiscretizationConnection
            raise ValueError("can only interpolate to "
                             "`QBX_SOURCE_QUAD_STAGE2`")

        # FIXME: would be nice if these were ordered by themselves
        stage_name_to_index_map = {
            None: 0,
            sym.QBX_SOURCE_STAGE1: 1,
            sym.QBX_SOURCE_STAGE2: 2,
            sym.QBX_SOURCE_QUAD_STAGE2: 3
        }
        stage_index_to_name_map = {
            i: name
            for name, i in stage_name_to_index_map.items()
        }

        from_stage = stage_name_to_index_map[from_dd.discr_stage]
        to_stage = stage_name_to_index_map[to_dd.discr_stage]

        for istage in range(from_stage, to_stage):
            conn = places._get_conn_from_cache(
                from_dd.geometry, stage_index_to_name_map[istage],
                stage_index_to_name_map[istage + 1])
            connections.append(conn)

    if from_dd.granularity is not to_dd.granularity:
        if to_dd.granularity is sym.GRANULARITY_NODE:
            pass
        elif to_dd.granularity is sym.GRANULARITY_CENTER:
            connections.append(CenterGranularityConnection(to_discr))
        elif to_dd.granularity is sym.GRANULARITY_ELEMENT:
            raise ValueError("Creating a connection to element granularity "
                             "is not allowed. Use Elementwise{Max,Min,Sum}.")
        else:
            raise ValueError(f"invalid to_dd granularity: {to_dd.granularity}")

    if from_dd.granularity is not to_dd.granularity:
        conn = DOFConnection(connections, from_dd=from_dd, to_dd=to_dd)
    else:
        from meshmode.discretization.connection import \
                ChainedDiscretizationConnection
        conn = ChainedDiscretizationConnection(connections,
                                               from_discr=from_discr)

    return conn
Exemple #2
0
def build_matrix(actx,
                 places,
                 exprs,
                 input_exprs,
                 domains=None,
                 auto_where=None,
                 context=None):
    """
    :arg actx: a :class:`~meshmode.array_context.ArrayContext`.
    :arg places: a :class:`~pytential.symbolic.execution.GeometryCollection`.
        Alternatively, any list or mapping that is a valid argument for its
        constructor can also be used.
    :arg exprs: an array of expressions corresponding to the output block
        rows of the matrix. May also be a single expression.
    :arg input_exprs: an array of expressions corresponding to the
        input block columns of the matrix. May also be a single expression.
    :arg domains: a list of discretization identifiers (see 'places') or
        *None* values indicating the domains on which each component of the
        solution vector lives.  *None* values indicate that the component
        is a scalar.  If *None*, *auto_where* or, if it is not provided,
        :class:`~pytential.symbolic.primitives.DEFAULT_SOURCE` is required
        to be a key in :attr:`places`.
    :arg auto_where: For simple source-to-self or source-to-target
        evaluations, find 'where' attributes automatically.
    """

    if context is None:
        context = {}

    from pytential import GeometryCollection
    if not isinstance(places, GeometryCollection):
        places = GeometryCollection(places, auto_where=auto_where)
    exprs = _prepare_expr(places, exprs, auto_where=auto_where)

    if not (isinstance(exprs, np.ndarray) and exprs.dtype.char == "O"):
        from pytools.obj_array import make_obj_array
        exprs = make_obj_array([exprs])

    try:
        input_exprs = list(input_exprs)
    except TypeError:
        # not iterable, wrap in a list
        input_exprs = [input_exprs]

    domains = _prepare_domains(len(input_exprs), places, domains,
                               places.auto_source)

    from pytential.symbolic.matrix import MatrixBuilder, is_zero
    nblock_rows = len(exprs)
    nblock_columns = len(input_exprs)
    blocks = np.zeros((nblock_rows, nblock_columns), dtype=np.object)

    dtypes = []
    for ibcol in range(nblock_columns):
        dep_source = places.get_geometry(domains[ibcol].geometry)
        dep_discr = places.get_discretization(domains[ibcol].geometry,
                                              domains[ibcol].discr_stage)

        mbuilder = MatrixBuilder(actx,
                                 dep_expr=input_exprs[ibcol],
                                 other_dep_exprs=(input_exprs[:ibcol] +
                                                  input_exprs[ibcol + 1:]),
                                 dep_source=dep_source,
                                 dep_discr=dep_discr,
                                 places=places,
                                 context=context)

        for ibrow in range(nblock_rows):
            block = mbuilder(exprs[ibrow])
            assert is_zero(block) or isinstance(block, np.ndarray)

            blocks[ibrow, ibcol] = block
            if isinstance(block, np.ndarray):
                dtypes.append(block.dtype)

    return actx.from_numpy(_bmat(blocks, dtypes))
Exemple #3
0
    # {{{ symbolic

    sym_u, sym_op = case.get_operator(ambient_dim)

    from pytential.symbolic.execution import _prepare_expr
    sym_prep_op = _prepare_expr(places, sym_op)

    # }}}

    # {{{ matrix

    index_set = case.get_block_indices(actx, density_discr)
    kwargs = dict(dep_expr=sym_u,
                  other_dep_exprs=[],
                  dep_source=places.get_geometry(dd.geometry),
                  dep_discr=density_discr,
                  places=places,
                  context=case.knl_concrete_kwargs)

    if block_builder_type == "qbx":
        from pytential.symbolic.matrix import MatrixBuilder
        from pytential.symbolic.matrix import \
                NearFieldBlockBuilder as BlockMatrixBuilder
    elif block_builder_type == "p2p":
        from pytential.symbolic.matrix import P2PMatrixBuilder as MatrixBuilder
        from pytential.symbolic.matrix import \
                FarFieldBlockBuilder as BlockMatrixBuilder
        kwargs["exclude_self"] = True
    else:
        raise ValueError(f"unknown block builder type: '{block_builder_type}'")