Пример #1
0
        def callback(self):
            del self._callback
            if op2.MPI.comm.size > 1:
                self._plex.distributeOverlap(1)
            self._grown_halos = True

            if reorder:
                with timed_region("Mesh: reorder"):
                    old_to_new = self._plex.getOrdering(PETSc.Mat.OrderingType.RCM).indices
                    reordering = np.empty_like(old_to_new)
                    reordering[old_to_new] = np.arange(old_to_new.size, dtype=old_to_new.dtype)
            else:
                # No reordering
                reordering = None

            # Mark OP2 entities and derive the resulting Plex renumbering
            with timed_region("Mesh: renumbering"):
                dmplex.mark_entity_classes(self._plex)
                self._entity_classes = dmplex.get_entity_classes(self._plex)
                self._plex_renumbering = dmplex.plex_renumbering(self._plex,
                                                                 self._entity_classes,
                                                                 reordering)

            with timed_region("Mesh: cell numbering"):
                # Derive a cell numbering from the Plex renumbering
                entity_dofs = np.zeros(topological_dim+1, dtype=np.int32)
                entity_dofs[-1] = 1

                self._cell_numbering = self._plex.createSection([1], entity_dofs,
                                                                perm=self._plex_renumbering)
                entity_dofs[:] = 0
                entity_dofs[0] = 1
                self._vertex_numbering = self._plex.createSection([1], entity_dofs,
                                                                  perm=self._plex_renumbering)

            # Note that for bendy elements, this needs to change.
            with timed_region("Mesh: coordinate field"):
                if periodic_coords is not None:
                    if self.ufl_cell().geometric_dimension() != 1:
                        raise NotImplementedError("Periodic coordinates in more than 1D are unsupported")
                    # We've been passed a periodic coordinate field, so use that.
                    self._coordinate_fs = functionspace.VectorFunctionSpace(self, "DG", 1)
                    self.coordinates = function.Function(self._coordinate_fs,
                                                         val=periodic_coords,
                                                         name="Coordinates")
                else:
                    self._coordinate_fs = functionspace.VectorFunctionSpace(self, "Lagrange", 1)

                    coordinates = dmplex.reordered_coords(self._plex, self._coordinate_fs._global_numbering,
                                                          (self.num_vertices(), geometric_dim))
                    self.coordinates = function.Function(self._coordinate_fs,
                                                         val=coordinates,
                                                         name="Coordinates")
            self._ufl_domain = ufl.Domain(self.coordinates)
            # Build a new ufl element for this function space with the
            # correct domain.  This is necessary since this function space
            # is in the cache and will be picked up by later
            # VectorFunctionSpace construction.
            self._coordinate_fs._ufl_element = self._coordinate_fs.ufl_element().reconstruct(domain=self.ufl_domain())
            # HACK alert!
            # Replace coordinate Function by one that has a real domain on it (but don't copy values)
            self.coordinates = function.Function(self._coordinate_fs, val=self.coordinates.dat)
            # Add subdomain_data to the measure objects we store with
            # the mesh.  These are weakrefs for consistency with the
            # "global" measure objects
            self._dx = ufl.Measure('cell', subdomain_data=weakref.ref(self.coordinates))
            self._ds = ufl.Measure('exterior_facet', subdomain_data=weakref.ref(self.coordinates))
            self._dS = ufl.Measure('interior_facet', subdomain_data=weakref.ref(self.coordinates))
            # Set the subdomain_data on all the default measures to this
            # coordinate field.
            # We don't set the domain on the measure since this causes
            # an uncollectable reference in the global space (dx is
            # global).  Furthermore, it's never used anyway.
            for measure in [ufl.dx, ufl.ds, ufl.dS]:
                measure._subdomain_data = weakref.ref(self.coordinates)
Пример #2
0
    def _from_dmplex(self, plex, geometric_dim=0,
                     periodic_coords=None, reorder=None):
        """ Create mesh from DMPlex object """

        self._plex = plex
        self.uid = utils._new_uid()

        # Mark exterior and interior facets
        # Note.  This must come before distribution, because otherwise
        # DMPlex will consider facets on the domain boundary to be
        # exterior, which is wrong.
        dmplex.label_facets(self._plex)

        if geometric_dim == 0:
            geometric_dim = plex.getDimension()

        # Distribute the dm to all ranks
        if op2.MPI.comm.size > 1:
            self.parallel_sf = plex.distribute(overlap=1)

        self._plex = plex

        if reorder:
            old_to_new = self._plex.getOrdering(PETSc.Mat.OrderingType.RCM).indices
            reordering = np.empty_like(old_to_new)
            reordering[old_to_new] = np.arange(old_to_new.size, dtype=old_to_new.dtype)
        else:
            # No reordering
            reordering = None

        # Mark OP2 entities and derive the resulting Plex renumbering
        dmplex.mark_entity_classes(self._plex)
        self._plex_renumbering = dmplex.plex_renumbering(self._plex, reordering)

        cStart, cEnd = self._plex.getHeightStratum(0)  # cells
        cell_vertices = self._plex.getConeSize(cStart)
        self._ufl_cell = ufl.Cell(fiat_utils._cells[geometric_dim][cell_vertices],
                                  geometric_dimension=geometric_dim)

        self._ufl_domain = ufl.Domain(self.ufl_cell(), data=self)
        dim = self._plex.getDimension()
        self._cells, self.cell_classes = dmplex.get_cells_by_class(self._plex)

        # Derive a cell numbering from the Plex renumbering
        cell_entity_dofs = np.zeros(dim+1, dtype=np.int32)
        cell_entity_dofs[-1] = 1
        self._cell_numbering = self._plex.createSection(1, [1],
                                                        cell_entity_dofs,
                                                        perm=self._plex_renumbering)

        self._cell_closure = None
        self.interior_facets = None
        self.exterior_facets = None

        # Note that for bendy elements, this needs to change.
        if periodic_coords is not None:
            if self.ufl_cell().geometric_dimension() != 1:
                raise NotImplementedError("Periodic coordinates in more than 1D are unsupported")
            # We've been passed a periodic coordinate field, so use that.
            self._coordinate_fs = functionspace.VectorFunctionSpace(self, "DG", 1)
            self.coordinates = function.Function(self._coordinate_fs,
                                                 val=periodic_coords,
                                                 name="Coordinates")
        else:
            self._coordinate_fs = functionspace.VectorFunctionSpace(self, "Lagrange", 1)

            coordinates = dmplex.reordered_coords(self._plex, self._coordinate_fs._global_numbering,
                                                  (self.num_vertices(), geometric_dim))
            self.coordinates = function.Function(self._coordinate_fs,
                                                 val=coordinates,
                                                 name="Coordinates")
        self._ufl_domain = ufl.Domain(self.coordinates)
        # Build a new ufl element for this function space with the
        # correct domain.  This is necessary since this function space
        # is in the cache and will be picked up by later
        # VectorFunctionSpace construction.
        self._coordinate_fs._ufl_element = self._coordinate_fs.ufl_element().reconstruct(domain=self.ufl_domain())
        # HACK alert!
        # Replace coordinate Function by one that has a real domain on it (but don't copy values)
        self.coordinates = function.Function(self._coordinate_fs, val=self.coordinates.dat)
        # Add domain and subdomain_data to the measure objects we store with the mesh.
        self._dx = ufl.Measure('cell', domain=self, subdomain_data=self.coordinates)
        self._ds = ufl.Measure('exterior_facet', domain=self, subdomain_data=self.coordinates)
        self._dS = ufl.Measure('interior_facet', domain=self, subdomain_data=self.coordinates)
        # Set the subdomain_data on all the default measures to this
        # coordinate field.  Also set the domain on the measure.
        for measure in [ufl.dx, ufl.ds, ufl.dS]:
            measure._subdomain_data = self.coordinates
            measure._domain = self.ufl_domain()