Esempio n. 1
0
    def local_to_global_map(self, bcs, lgmap=None):
        r"""Return a map from process local dof numbering to global dof numbering.

        If BCs is provided, mask out those dofs which match the BC nodes."""
        # Caching these things is too complicated, since it depends
        # not just on the bcs, but also the parent space, and anything
        # this space has been recursively split out from [e.g. inside
        # fieldsplit]
        if bcs is None or len(bcs) == 0:
            return lgmap or self.dof_dset.lgmap
        for bc in bcs:
            fs = bc.function_space()
            while fs.component is not None and fs.parent is not None:
                fs = fs.parent
            if fs.topological != self.topological:
                raise RuntimeError(
                    "DirichletBC defined on a different FunctionSpace!")
        unblocked = any(bc.function_space().component is not None
                        for bc in bcs)
        if lgmap is None:
            lgmap = self.dof_dset.lgmap
            if unblocked:
                indices = lgmap.indices.copy()
                bsize = 1
            else:
                indices = lgmap.block_indices.copy()
                bsize = lgmap.getBlockSize()
                assert bsize == self.value_size
        else:
            # MatBlock case, LGMap is already unrolled.
            indices = lgmap.block_indices.copy()
            bsize = lgmap.getBlockSize()
            unblocked = True
        nodes = []
        for bc in bcs:
            if bc.function_space().component is not None:
                nodes.append(bc.nodes * self.value_size +
                             bc.function_space().component)
            elif unblocked:
                tmp = bc.nodes * self.value_size
                for i in range(self.value_size):
                    nodes.append(tmp + i)
            else:
                nodes.append(bc.nodes)
        nodes = numpy.unique(numpy.concatenate(nodes))
        indices[nodes] = -1
        return PETSc.LGMap().create(indices, bsize=bsize, comm=lgmap.comm)
Esempio n. 2
0
    def lgmap(self, V, bcs, lgmap=None):
        assert len(V) == 1, "lgmap should not be called on MixedFunctionSpace"
        V = V.topological
        if bcs is None or len(bcs) == 0:
            return lgmap or V.dof_dset.lgmap

        # Boundary condition list *must* be collectively ordered already.
        # Key is a sorted list of bc subdomain, bc method, bc component.
        bc_key = []
        for bc in bcs:
            fs = bc.function_space()
            while fs.component is not None and fs.parent is not None:
                fs = fs.parent
            if fs.topological != V:
                raise RuntimeError("DirichletBC defined on a different FunctionSpace!")
            bc_key.append(bc._cache_key)

        def key(a):
            tpl, *rest = a
            if len(tpl) == 1 and isinstance(tpl[0], str):
                # tpl = ("some_string", )
                return (True, tpl[0], (), tuple(rest))
            else:
                # Ex:
                # tpl = ((facet_dim, ((1,), (2,), (3,))),
                #        (edge_dim, ((1, 3), (1, 4))),
                #        (vert_dim, ((1, 3, 4), )))
                return (False, "", tpl, tuple(rest))

        bc_key = tuple(sorted(bc_key, key=key))
        node_set = V.node_set
        key = (node_set, V.value_size, lgmap is None, bc_key)
        try:
            return self.map_cache[key]
        except KeyError:
            pass
        unblocked = any(bc.function_space().component is not None for bc in bcs)
        if lgmap is None:
            lgmap = V.dof_dset.lgmap
            if unblocked:
                indices = lgmap.indices.copy()
                bsize = 1
            else:
                indices = lgmap.block_indices.copy()
                bsize = lgmap.getBlockSize()
                assert bsize == V.value_size
        else:
            # MatBlock case, LGMap is already unrolled.
            indices = lgmap.block_indices.copy()
            bsize = lgmap.getBlockSize()
            unblocked = True
        nodes = []
        for bc in bcs:
            if bc.function_space().component is not None:
                nodes.append(bc.nodes * V.value_size + bc.function_space().component)
            elif unblocked:
                tmp = bc.nodes * V.value_size
                for i in range(V.value_size):
                    nodes.append(tmp + i)
            else:
                nodes.append(bc.nodes)
        nodes = numpy.unique(numpy.concatenate(nodes))
        indices[nodes] = -1
        return self.map_cache.setdefault(key, PETSc.LGMap().create(indices, bsize=bsize, comm=lgmap.comm))