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.")
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)
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 = {}