Beispiel #1
0
    def cell_closure(self):
        """2D array of ordered cell closures

        Each row contains ordered cell entities for a cell, one row per cell.
        """
        plex = self._plex
        topological_dim = plex.getDimension()

        # Cell numbering and global vertex numbering
        cell_numbering = self._cell_numbering
        vertex_numbering = self._vertex_numbering.createGlobalSection(plex.getPointSF())

        cStart, cEnd = plex.getHeightStratum(0)  # cells
        cell_facets = plex.getConeSize(cStart)

        if topological_dim + 1 == cell_facets:
            # Simplex mesh
            a_closure = plex.getTransitiveClosure(cStart)[0]

            entity_per_cell = np.zeros(topological_dim + 1, dtype=np.int32)
            for dim in xrange(topological_dim + 1):
                start, end = plex.getDepthStratum(dim)
                entity_per_cell[dim] = sum(map(lambda idx: start <= idx < end,
                                               a_closure))

            return dmplex.closure_ordering(plex, vertex_numbering,
                                           cell_numbering, entity_per_cell)

        elif topological_dim == 2 and cell_facets == 4:
            # Quadrilateral mesh
            cell_ranks = dmplex.get_cell_remote_ranks(plex)

            facet_orientations = dmplex.quadrilateral_facet_orientations(
                plex, vertex_numbering, cell_ranks)

            cell_orientations = dmplex.orientations_facet2cell(
                plex, vertex_numbering, cell_ranks,
                facet_orientations, cell_numbering)

            dmplex.exchange_cell_orientations(plex,
                                              cell_numbering,
                                              cell_orientations)

            return dmplex.quadrilateral_closure_ordering(
                plex, vertex_numbering, cell_numbering, cell_orientations)

        else:
            raise RuntimeError("Unsupported mesh: neither simplex, nor quadrilateral.")
Beispiel #2
0
    def cell_closure(self):
        """2D array of ordered cell closures

        Each row contains ordered cell entities for a cell, one row per cell.
        """
        dm = self._plex

        a_cell = dm.getHeightStratum(0)[0]
        a_closure = dm.getTransitiveClosure(a_cell)[0]
        topological_dimension = dm.getDimension()

        entity_per_cell = np.zeros(topological_dimension + 1, dtype=np.int32)
        for dim in xrange(topological_dimension + 1):
            start, end = dm.getDepthStratum(dim)
            entity_per_cell[dim] = sum(map(lambda idx: start <= idx < end, a_closure))

        return dmplex.closure_ordering(dm, dm.getDefaultGlobalSection(),
                                       self._cell_numbering, entity_per_cell)
Beispiel #3
0
    def __init__(self, mesh, element, name=None, dim=1, rank=0):
        """
        :param mesh: :class:`Mesh` to build this space on
        :param element: :class:`ufl.FiniteElementBase` to build this space from
        :param name: user-defined name for this space
        :param dim: vector space dimension of a :class:`.VectorFunctionSpace`
        :param rank: rank of the space, not the value rank
        """

        self._ufl_element = element

        # Compute the FIAT version of the UFL element above
        self.fiat_element = fiat_utils.fiat_from_ufl_element(element)

        if isinstance(mesh, mesh_t.ExtrudedMesh):
            # Set up some extrusion-specific things
            # The bottom layer maps will come from element_dof_list
            # dof_count is the total number of dofs in the extruded mesh

            # Get the flattened version of the FIAT element
            self.flattened_element = self.fiat_element.flattened_element()
            entity_dofs = self.flattened_element.entity_dofs()
            self._dofs_per_cell = [len(entity)*len(entity[0]) for d, entity in entity_dofs.iteritems()]

            # Compute the number of DoFs per dimension on top/bottom and sides
            entity_dofs = self.fiat_element.entity_dofs()
            top_dim = mesh._plex.getDimension()
            self._xtr_hdofs = [len(entity_dofs[(d, 0)][0]) for d in range(top_dim+1)]
            self._xtr_vdofs = [len(entity_dofs[(d, 1)][0]) for d in range(top_dim+1)]

            # Compute the dofs per column
            self.dofs_per_column = eutils.compute_extruded_dofs(self.fiat_element,
                                                                self.flattened_element.entity_dofs(),
                                                                mesh._layers)

            # Compute the offset for the extrusion process
            self.offset = eutils.compute_offset(self.fiat_element.entity_dofs(),
                                                self.flattened_element.entity_dofs(),
                                                self.fiat_element.space_dimension())

            # Compute the top and bottom masks to identify boundary dofs
            b_mask = self.fiat_element.get_lower_mask()
            t_mask = self.fiat_element.get_upper_mask()

            self.bt_masks = (b_mask, t_mask)

            self.extruded = True

            self._dofs_per_entity = self.dofs_per_column
        else:
            # If not extruded specific, set things to None/False, etc.
            self.offset = None
            self.bt_masks = None
            self.dofs_per_column = np.zeros(1, np.int32)
            self.extruded = False

            entity_dofs = self.fiat_element.entity_dofs()
            self._dofs_per_entity = [len(entity[0]) for d, entity in entity_dofs.iteritems()]
            self._dofs_per_cell = [len(entity)*len(entity[0]) for d, entity in entity_dofs.iteritems()]

        self.name = name
        self._dim = dim
        self._mesh = mesh
        self._index = None

        # Create the PetscSection mapping topological entities to DoFs
        self._global_numbering = mesh._plex.createSection(1, [1], self._dofs_per_entity,
                                                          perm=mesh._plex_renumbering)
        mesh._plex.setDefaultSection(self._global_numbering)
        self._universal_numbering = mesh._plex.getDefaultGlobalSection()

        # Re-initialise the DefaultSF with the numbering for this FS
        mesh._plex.createDefaultSF(self._global_numbering,
                                   self._universal_numbering)

        # Derive the Halo from the DefaultSF
        self._halo = halo.Halo(mesh._plex.getDefaultSF(),
                               self._global_numbering,
                               self._universal_numbering)

        # Compute entity class offsets
        self.dof_classes = [0, 0, 0, 0]
        for d in range(mesh._plex.getDimension()+1):
            ncore = mesh._plex.getStratumSize("op2_core", d)
            nowned = mesh._plex.getStratumSize("op2_non_core", d)
            nhalo = mesh._plex.getStratumSize("op2_exec_halo", d)
            ndofs = self._dofs_per_entity[d]
            self.dof_classes[0] += ndofs * ncore
            self.dof_classes[1] += ndofs * (ncore + nowned)
            self.dof_classes[2] += ndofs * (ncore + nowned + nhalo)
            self.dof_classes[3] += ndofs * (ncore + nowned + nhalo)

        self._node_count = self._global_numbering.getStorageSize()

        # Re-order cell closures from the Plex
        if mesh._cell_closure is None:
            entity_dofs = self.fiat_element.entity_dofs()
            entity_per_cell = [len(entity) for d, entity in entity_dofs.iteritems()]
            entity_per_cell = np.array(entity_per_cell, dtype=np.int32)
            mesh._cell_closure = dmplex.closure_ordering(mesh._plex,
                                                         self._universal_numbering,
                                                         mesh._cell_numbering,
                                                         entity_per_cell)

        if isinstance(self._mesh, mesh_t.ExtrudedMesh):
            self.cell_node_list = dmplex.get_extruded_cell_nodes(mesh._plex,
                                                                 self._global_numbering,
                                                                 mesh._cell_closure,
                                                                 self.fiat_element,
                                                                 sum(self._dofs_per_cell))
        else:
            self.cell_node_list = dmplex.get_cell_nodes(self._global_numbering,
                                                        mesh._cell_closure,
                                                        sum(self._dofs_per_cell))

        if mesh._plex.getStratumSize("interior_facets", 1) > 0:
            # Compute the facet_numbering and store with the parent mesh
            if mesh.interior_facets is None:
                # Order interior facets by OP2 entity class
                interior_facets, interior_facet_classes = \
                    dmplex.get_facets_by_class(mesh._plex, "interior_facets")

                interior_local_facet_number, interior_facet_cell = \
                    dmplex.facet_numbering(mesh._plex, "interior",
                                           interior_facets,
                                           mesh._cell_numbering,
                                           mesh._cell_closure)

                mesh.interior_facets = mesh_t._Facets(mesh, interior_facet_classes,
                                                      "interior",
                                                      interior_facet_cell,
                                                      interior_local_facet_number)

            interior_facet_cells = mesh.interior_facets.facet_cell
            self.interior_facet_node_list = \
                dmplex.get_facet_nodes(interior_facet_cells,
                                       self.cell_node_list)
        else:
            self.interior_facet_node_list = None
            if mesh.interior_facets is None:
                mesh.interior_facets = mesh_t._Facets(self, 0, "exterior", None, None)

        if mesh._plex.getStratumSize("exterior_facets", 1) > 0:
            # Compute the facet_numbering and store with the parent mesh
            if mesh.exterior_facets is None:

                # Order exterior facets by OP2 entity class
                exterior_facets, exterior_facet_classes = \
                    dmplex.get_facets_by_class(mesh._plex, "exterior_facets")

                # Derive attached boundary IDs
                if mesh._plex.hasLabel("boundary_ids"):
                    boundary_ids = np.zeros(exterior_facets.size, dtype=np.int32)
                    for i, facet in enumerate(exterior_facets):
                        boundary_ids[i] = mesh._plex.getLabelValue("boundary_ids", facet)

                    unique_ids = np.sort(mesh._plex.getLabelIdIS("boundary_ids").indices)
                else:
                    boundary_ids = None
                    unique_ids = None

                exterior_local_facet_number, exterior_facet_cell = \
                    dmplex.facet_numbering(mesh._plex, "exterior",
                                           exterior_facets,
                                           mesh._cell_numbering,
                                           mesh._cell_closure)

                mesh.exterior_facets = mesh_t._Facets(mesh, exterior_facet_classes,
                                                      "exterior",
                                                      exterior_facet_cell,
                                                      exterior_local_facet_number,
                                                      boundary_ids,
                                                      unique_markers=unique_ids)

            exterior_facet_cells = mesh.exterior_facets.facet_cell
            self.exterior_facet_node_list = \
                dmplex.get_facet_nodes(exterior_facet_cells,
                                       self.cell_node_list)
        else:
            self.exterior_facet_node_list = None
            if mesh.exterior_facets is None:
                if mesh._plex.hasLabel("boundary_ids"):
                    unique_ids = np.sort(mesh._plex.getLabelIdIS("boundary_ids").indices)
                else:
                    unique_ids = None
                mesh.exterior_facets = mesh_t._Facets(self, 0, "exterior", None, None,
                                                      unique_markers=unique_ids)

        # Note: this is the function space rank. The value rank may be different.
        self.rank = rank

        # Empty map caches. This is a sui generis cache
        # implementation because of the need to support boundary
        # conditions.
        self._cell_node_map_cache = {}
        self._exterior_facet_map_cache = {}
        self._interior_facet_map_cache = {}