Пример #1
0
def from_vertices_and_simplices(vertices, simplices, order=1, fix_orientation=False):
    """Imports a mesh from a numpy array of vertices and an array
    of simplices.

    :arg vertices:
        An array of vertex coordinates with shape
        *(ambient_dim, nvertices)*
    :arg simplices:
        An array *(nelements, nvertices)* of (mesh-wide)
        vertex indices.
    """
    from meshmode.mesh import Mesh
    from meshmode.mesh.generation import make_group_from_vertices

    grp = make_group_from_vertices(vertices, simplices, order)

    if fix_orientation:
        if grp.dim != vertices.shape[0]:
            raise ValueError("can only fix orientation of volume meshes")

        from meshmode.mesh.processing import (
                find_volume_mesh_element_group_orientation,
                flip_simplex_element_group)
        orient = find_volume_mesh_element_group_orientation(vertices, grp)
        grp = flip_simplex_element_group(vertices, grp, orient < 0)

    return Mesh(
            vertices=vertices, groups=[grp],
            is_conforming=True)
Пример #2
0
def from_vertices_and_simplices(vertices, simplices, order=1, fix_orientation=False):
    """Imports a mesh from a numpy array of vertices and an array
    of simplices.

    :arg vertices:
        An array of vertex coordinates with shape
        *(ambient_dim, nvertices)*
    :arg simplices:
        An array *(nelements, nvertices)* of (mesh-wide)
        vertex indices.
    """
    from meshmode.mesh import Mesh
    from meshmode.mesh.generation import make_group_from_vertices

    grp = make_group_from_vertices(vertices, simplices, order)

    if fix_orientation:
        if grp.dim != vertices.shape[0]:
            raise ValueError("can only fix orientation of volume meshes")

        from meshmode.mesh.processing import (
                find_volume_mesh_element_group_orientation,
                flip_simplex_element_group)
        orient = find_volume_mesh_element_group_orientation(vertices, grp)
        grp = flip_simplex_element_group(vertices, grp, orient < 0)

    return Mesh(
            vertices=vertices, groups=[grp],
            is_conforming=True)
Пример #3
0
def from_vertices_and_simplices(vertices,
                                simplices,
                                order=1,
                                fix_orientation=False):
    """Imports a mesh from a numpy array of vertices and an array
    of simplices.

    :arg vertices:
        An array of vertex coordinates with shape
        *(ambient_dim, nvertices)*
    :arg simplices:
        An array *(nelements, nvertices)* of (mesh-wide)
        vertex indices.
    """
    from meshmode.mesh import Mesh
    from meshmode.mesh.generation import make_group_from_vertices

    grp = make_group_from_vertices(vertices, simplices, order)

    if fix_orientation:
        from meshmode.mesh.processing import (
            find_volume_mesh_element_group_orientation,
            flip_simplex_element_group)
        orient = find_volume_mesh_element_group_orientation(vertices, grp)
        grp = flip_simplex_element_group(vertices, grp, orient < 0)

    return Mesh(vertices=vertices,
                groups=[grp],
                nodal_adjacency=None,
                facial_adjacency_groups=None)
Пример #4
0
def from_vertices_and_simplices(vertices, simplices, order=1, fix_orientation=False):
    """Imports a mesh from a numpy array of vertices and an array
    of simplices.

    :arg vertices:
        An array of vertex coordinates with shape
        *(ambient_dim, nvertices)*
    :arg simplices:
        An array *(nelements, nvertices)* of (mesh-wide)
        vertex indices.
    """
    from meshmode.mesh import Mesh
    from meshmode.mesh.generation import make_group_from_vertices

    grp = make_group_from_vertices(vertices, simplices, order)

    if fix_orientation:
        from meshmode.mesh.processing import (
                find_volume_mesh_element_group_orientation,
                flip_simplex_element_group)
        orient = find_volume_mesh_element_group_orientation(vertices, grp)
        grp = flip_simplex_element_group(vertices, grp, orient < 0)

    return Mesh(
            vertices=vertices, groups=[grp],
            nodal_adjacency=None,
            facial_adjacency_groups=None)
Пример #5
0
def _get_firedrake_orientations(fdrake_mesh, unflipped_group, vertices,
                                cells_to_use,
                                normals=None, no_normals_warn=True):
    r"""
    Return the orientations of the mesh elements:

    :arg fdrake_mesh: As described in :func:`import_firedrake_mesh`
    :arg unflipped_group: A :class:`SimplexElementGroup` instance with
        (potentially) some negatively oriented elements.
    :arg vertices: The vertex coordinates as a numpy array of shape
        *(ambient_dim, nvertices)* (the vertices of *unflipped_group*)
    :arg normals: As described in :func:`import_firedrake_mesh`
    :arg no_normals_warn: As described in :func:`import_firedrake_mesh`
    :arg cells_to_use: If *None*, then ignored. Otherwise, a numpy array
        of unique firedrake cell indices indicating which cells to use.

    :return: A numpy array, the *i*\ th element is > 0 if the *i*\ th element
        is positively oriented, < 0 if negatively oriented.
        Mesh must have co-dimension 0 or 1. If *cells_to_use* is not
        *None*, then the *i*\ th entry corresponds to the
        *cells_to_use[i]*\ th element.
    """
    # compute orientations
    tdim = fdrake_mesh.topological_dimension()
    gdim = fdrake_mesh.geometric_dimension()

    orient = None
    if gdim == tdim:
        # If the co-dimension is 0, :mod:`meshmode` has a convenient
        # function to compute cell orientations
        from meshmode.mesh.processing import \
            find_volume_mesh_element_group_orientation

        orient = find_volume_mesh_element_group_orientation(vertices,
                                                            unflipped_group)

    elif tdim == 1 and gdim == 2:
        # In this case we have a 1-surface embedded in 2-space.
        # Firedrake does not provide any convenient way of
        # letting the user set cell orientations in this case, so we
        # have to ask the user for cell normals directly.
        if cells_to_use is None:
            num_cells = fdrake_mesh.num_cells()
        else:
            num_cells = np.size(cells_to_use)
        orient = np.ones(num_cells)
        if normals:
            for i, (normal, vert_indices) in enumerate(
                    zip(np.array(normals), unflipped_group.vertex_indices)):
                edge = vertices[:, vert_indices[1]] - vertices[:, vert_indices[0]]
                if np.cross(normal, edge) < 0:
                    orient[i] = -1.0
        elif no_normals_warn:
            warn("Assuming all elements are positively-oriented.")

    elif tdim == 2 and gdim == 3:
        # In this case we have a 2-surface embedded in 3-space.
        # In this case, we assume the user has called
        # :func:`firedrake.mesh.MeshGeometry.init_cell_orientations`, see
        # https://www.firedrakeproject.org/variational-problems.html#ensuring-consistent-cell-orientations  # noqa : E501
        # for a tutorial on how these are usually initialized.
        #
        # Unfortunately, *init_cell_orientations* is currently only implemented
        # in 3D, so we can't use this in the 1/2 case.
        orient = fdrake_mesh.cell_orientations().dat.data
        if cells_to_use is not None:
            orient = orient[cells_to_use]
        r"""
            Convert (0 \implies negative, 1 \implies positive) to
            (-1 \implies negative, 1 \implies positive)
        """
        orient *= 2
        orient -= 1
    # Make sure the mesh fell into one of the cases
    # Nb : This should be guaranteed by previous checks,
    #      but is here anyway in case of future development.
    assert orient is not None
    return orient
Пример #6
0
    def orientations(self):
        """
            Return the orientations of the mesh elements:
            an array, the *i*th element is > 0 if the *ith* element
            is positively oriented, < 0 if negatively oriented

            :arg normals: _Only_ used if :arg:`mesh` is a 1-surface
                embedded in 2-space. In this case,
                - If *None* then
                  all elements are assumed to be positively oriented.
                - Else, should be a list/array whose *i*th entry
                  is the normal for the *i*th element (*i*th
                  in :arg:`mesh`*.coordinate.function_space()*'s
                  :attribute:`cell_node_list`)

            :arg no_normals_warn: If *True*, raises a warning
                if :arg:`mesh` is a 1-surface embedded in 2-space
                and :arg:`normals` is *None*.
        """
        if self._orient is None:
            # compute orientations
            tdim = self.analog().topological_dimension()
            gdim = self.analog().geometric_dimension()

            orient = None
            if gdim == tdim:
                # We use :mod:`meshmode` to check our orientations
                from meshmode.mesh.processing import \
                    find_volume_mesh_element_group_orientation

                orient = \
                    find_volume_mesh_element_group_orientation(self.vertices(),
                                                               self.group())

            if tdim == 1 and gdim == 2:
                # In this case we have a 1-surface embedded in 2-space
                orient = np.ones(self.nelements())
                if self._normals:
                    for i, (normal, vertices) in enumerate(zip(
                            np.array(self._normals), self.vertices())):
                        if np.cross(normal, vertices) < 0:
                            orient[i] = -1.0
                elif self._no_normals_warn:
                    warn("Assuming all elements are positively-oriented.")

            elif tdim == 2 and gdim == 3:
                # In this case we have a 2-surface embedded in 3-space
                orient = self.analog().cell_orientations().dat.data
                r"""
                    Convert (0 \implies negative, 1 \implies positive) to
                    (-1 \implies negative, 1 \implies positive)
                """
                orient *= 2
                orient -= np.ones(orient.shape, dtype=orient.dtype)

            self._orient = orient
            #Make sure the mesh fell into one of the cases
            """
              NOTE : This should be guaranteed by previous checks,
                     but is here anyway in case of future development.
            """
            assert self._orient is not None

        return self._orient