Ejemplo n.º 1
0
    def get_tesselated_nodes(group, tesselation, elements):
        """
        Compute the nodes of the child elements according to the tesselation.

        :arg group: An instance of :class:`meshmode.mesh.SimplexElementGroup`
        :arg tesselation: With attributes `ref_vertices`, `children`
        :arg elements: A list of (group-relative) element numbers

        :return: A :class:`dict` mapping element numbers to node
            coordinates, with each value in the map having shape
            ``(ambient_dim, nchildren, nunit_nodes)``.
            The ordering of the child nodes follows the ordering
            of ``tesselation.children.``
        """
        assert len(group.vertex_indices[0]) == group.dim + 1

        from meshmode.mesh.refinement.utils import map_unit_nodes_to_children

        # Get child unit node coordinates.
        child_unit_nodes = np.hstack(
            list(map_unit_nodes_to_children(group.unit_nodes, tesselation)))

        resamp_mat = mp.resampling_matrix(
            mp.simplex_best_available_basis(group.dim, group.order),
            child_unit_nodes, group.unit_nodes)

        resamp_unit_nodes = np.einsum("cu,deu->edc", resamp_mat,
                                      group.nodes[:, elements])

        ambient_dim = len(group.nodes)
        nunit_nodes = len(group.unit_nodes[0])

        return dict((elem, resamp_unit_nodes[ielem].reshape((ambient_dim, -1,
                                                             nunit_nodes)))
                    for ielem, elem in enumerate(elements))
Ejemplo n.º 2
0
    def get_tesselated_nodes(group, tesselation, elements):
        """
        Compute the nodes of the child elements according to the tesselation.

        :arg group: An instance of :class:`meshmode.mesh.SimplexElementGroup`
        :arg tesselation: With attributes `ref_vertices`, `children`
        :arg elements: A list of (group-relative) element numbers

        :return: A :class:`dict` mapping element numbers to node
            coordinates, with each value in the map having shape
            ``(ambient_dim, nchildren, nunit_nodes)``.
            The ordering of the child nodes follows the ordering
            of ``tesselation.children.``
        """
        assert len(group.vertex_indices[0]) == group.dim + 1

        from meshmode.mesh.refinement.utils import map_unit_nodes_to_children

        # Get child unit node coordinates.
        child_unit_nodes = np.hstack(list(
            map_unit_nodes_to_children(group.unit_nodes, tesselation)))

        resamp_mat = mp.resampling_matrix(
            mp.simplex_best_available_basis(group.dim, group.order),
            child_unit_nodes,
            group.unit_nodes)

        resamp_unit_nodes = np.einsum("cu,deu->edc",
                                      resamp_mat,
                                      group.nodes[:, elements])

        ambient_dim = len(group.nodes)
        nunit_nodes = len(group.unit_nodes[0])

        return dict((elem,
            resamp_unit_nodes[ielem].reshape(
                 (ambient_dim, -1, nunit_nodes)))
            for ielem, elem in enumerate(elements))
Ejemplo n.º 3
0
def _(meg: _ModepyElementGroup, el_tess_info, elements):
    shape = meg._modepy_shape
    space = meg._modepy_space

    # get child unit node coordinates.
    from meshmode.mesh.refinement.utils import map_unit_nodes_to_children
    child_unit_nodes = np.hstack(
        list(map_unit_nodes_to_children(meg, meg.unit_nodes, el_tess_info)))

    # resample child nodes to ambient coordinates
    resampling_mat = mp.resampling_matrix(
        mp.basis_for_space(space, shape).functions, child_unit_nodes,
        meg.unit_nodes)

    resampled_unit_nodes = np.einsum("cu,deu->edc", resampling_mat,
                                     meg.nodes[:, elements])

    ambient_dim = len(meg.nodes)
    nunit_nodes = len(meg.unit_nodes[0])

    return {
        el: resampled_unit_nodes[iel].reshape((ambient_dim, -1, nunit_nodes))
        for iel, el in enumerate(elements)
    }
Ejemplo n.º 4
0
def _build_interpolation_batches_for_group(queue, group_idx,
                                           coarse_discr_group,
                                           fine_discr_group, record):
    r"""
    To map between discretizations, we sort each of the fine mesh
    elements into an interpolation batch.  Which batch they go
    into is determined by where the refined unit nodes live
    relative to the coarse reference element.

    For instance, consider the following refinement::

         ______      ______
        |\     |    |\    e|
        | \    |    |d\    |
        |  \   |    |__\   |
        |   \  | => |\c|\  |
        |    \ |    |a\|b\ |
        |     \|    |  |  \|
         ‾‾‾‾‾‾      ‾‾‾‾‾‾

    Here, the discretization unit nodes for elements a,b,c,d,e
    will each have different positions relative to the reference
    element, so each element gets its own batch. On the other
    hand, for::

         ______      ______
        |\     |    |\ f|\e|
        | \    |    |d\ |g\|
        |  \   |    |__\|__|
        |   \  | => |\c|\  |
        |    \ |    |a\|b\h|
        |     \|    |  |  \|
         ‾‾‾‾‾‾      ‾‾‾‾‾‾

    the pairs {a,e}, {b,f}, {c,g}, {d,h} can share interpolation
    batches because their unit nodes are mapped from the same part
    of the reference element.
    """
    from meshmode.discretization.connection.direct import InterpolationBatch

    num_children = len(record.tesselation.children) \
                   if record.tesselation else 0
    from_bins = [[] for i in range(1 + num_children)]
    to_bins = [[] for i in range(1 + num_children)]
    for elt_idx, refinement_result in enumerate(record.element_mapping):
        if len(refinement_result) == 1:
            # Not refined -> interpolates to self
            from_bins[0].append(elt_idx)
            to_bins[0].append(refinement_result[0])
        else:
            assert len(refinement_result) == num_children
            # Refined -> interpolates to children
            for from_bin, to_bin, child_idx in zip(from_bins[1:], to_bins[1:],
                                                   refinement_result):
                from_bin.append(elt_idx)
                to_bin.append(child_idx)

    fine_unit_nodes = fine_discr_group.unit_nodes
    from meshmode.mesh.refinement.utils import map_unit_nodes_to_children
    mapped_unit_nodes = map_unit_nodes_to_children(fine_unit_nodes,
                                                   record.tesselation)

    from itertools import chain
    for from_bin, to_bin, unit_nodes in zip(
            from_bins, to_bins, chain([fine_unit_nodes], mapped_unit_nodes)):
        if not from_bin:
            continue
        yield InterpolationBatch(
            from_group_index=group_idx,
            from_element_indices=cl.array.to_device(queue,
                                                    np.asarray(from_bin)),
            to_element_indices=cl.array.to_device(queue, np.asarray(to_bin)),
            result_unit_nodes=unit_nodes,
            to_element_face=None)
Ejemplo n.º 5
0
def _build_interpolation_batches_for_group(
        queue, group_idx, coarse_discr_group, fine_discr_group, record):
    r"""
    To map between discretizations, we sort each of the fine mesh
    elements into an interpolation batch.  Which batch they go
    into is determined by where the refined unit nodes live
    relative to the coarse reference element.

    For instance, consider the following refinement::

         ______      ______
        |\     |    |\    e|
        | \    |    |d\    |
        |  \   |    |__\   |
        |   \  | => |\c|\  |
        |    \ |    |a\|b\ |
        |     \|    |  |  \|
         ‾‾‾‾‾‾      ‾‾‾‾‾‾

    Here, the discretization unit nodes for elements a,b,c,d,e
    will each have different positions relative to the reference
    element, so each element gets its own batch. On the other
    hand, for::

         ______      ______
        |\     |    |\ f|\e|
        | \    |    |d\ |g\|
        |  \   |    |__\|__|
        |   \  | => |\c|\  |
        |    \ |    |a\|b\h|
        |     \|    |  |  \|
         ‾‾‾‾‾‾      ‾‾‾‾‾‾

    the pairs {a,e}, {b,f}, {c,g}, {d,h} can share interpolation
    batches because their unit nodes are mapped from the same part
    of the reference element.
    """
    from meshmode.discretization.connection.direct import InterpolationBatch

    num_children = len(record.tesselation.children) \
                   if record.tesselation else 0
    from_bins = [[] for i in range(1 + num_children)]
    to_bins = [[] for i in range(1 + num_children)]
    for elt_idx, refinement_result in enumerate(record.element_mapping):
        if len(refinement_result) == 1:
            # Not refined -> interpolates to self
            from_bins[0].append(elt_idx)
            to_bins[0].append(refinement_result[0])
        else:
            assert len(refinement_result) == num_children
            # Refined -> interpolates to children
            for from_bin, to_bin, child_idx in zip(
                    from_bins[1:], to_bins[1:], refinement_result):
                from_bin.append(elt_idx)
                to_bin.append(child_idx)

    fine_unit_nodes = fine_discr_group.unit_nodes
    from meshmode.mesh.refinement.utils import map_unit_nodes_to_children
    mapped_unit_nodes = map_unit_nodes_to_children(
        fine_unit_nodes, record.tesselation)

    from itertools import chain
    for from_bin, to_bin, unit_nodes in zip(
            from_bins, to_bins,
            chain([fine_unit_nodes], mapped_unit_nodes)):
        if not from_bin:
            continue
        yield InterpolationBatch(
            from_group_index=group_idx,
            from_element_indices=cl.array.to_device(queue, np.asarray(from_bin)),
            to_element_indices=cl.array.to_device(queue, np.asarray(to_bin)),
            result_unit_nodes=unit_nodes,
            to_element_face=None)