def test_prism_hdiv(prism_mesh, space, degree, horiz_expected, vert_expected):
    W0_h = FiniteElement(space, "triangle", degree)
    W1_h = FiniteElement("DG", "triangle", degree - 1)

    W0_v = FiniteElement("DG", "interval", degree - 1)
    W0 = HDiv(OuterProductElement(W0_h, W0_v))

    W1_v = FiniteElement("CG", "interval", degree)
    W1 = HDiv(OuterProductElement(W1_h, W1_v))

    V = FunctionSpace(prism_mesh, W0+W1)
    assert horiz_expected == horiz_facet_support_dofs(V.fiat_element)
    assert vert_expected == vert_facet_support_dofs(V.fiat_element)
Example #2
0
def test_prism_hcurl(prism_mesh, space, degree, horiz_expected, vert_expected):
    W0_h = FiniteElement("CG", "triangle", degree)
    W1_h = FiniteElement(space, "triangle", degree)

    W0_v = FiniteElement("DG", "interval", degree - 1)
    W0 = HCurl(OuterProductElement(W0_h, W0_v))

    W1_v = FiniteElement("CG", "interval", degree)
    W1 = HCurl(OuterProductElement(W1_h, W1_v))

    V = FunctionSpace(prism_mesh, W0 + W1)
    assert horiz_expected == horiz_facet_support_dofs(V.fiat_element)
    assert vert_expected == vert_facet_support_dofs(V.fiat_element)
Example #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 = fiat_utils.FlattenedElement(self.fiat_element)

            # 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
            #
            # Sorting the keys of the closure entity dofs, the whole cell
            # comes last [-1], before that the horizontal facet [-2], before
            # that vertical facets [-3]. We need the horizontal facets here.
            closure_dofs = self.fiat_element.entity_closure_dofs()
            b_mask = closure_dofs[sorted(closure_dofs.keys())[-2]][0]
            t_mask = closure_dofs[sorted(closure_dofs.keys())[-2]][1]
            self.bt_masks = {}
            self.bt_masks["topological"] = (b_mask, t_mask)  # conversion to tuple
            # Geometric facet dofs
            facet_dofs = horiz_facet_support_dofs(self.fiat_element)
            self.bt_masks["geometric"] = (facet_dofs[0], facet_dofs[1])

            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.name = name
        self._dim = dim
        self._mesh = mesh
        self._index = None

        dm = PETSc.DMShell().create()
        dm.setAttr('__fs__', weakref.ref(self))
        dm.setPointSF(mesh._plex.getPointSF())
        # Create the PetscSection mapping topological entities to DoFs
        sec = mesh._plex.createSection([1], self._dofs_per_entity,
                                       perm=mesh._plex_renumbering)
        dm.setDefaultSection(sec)
        self._global_numbering = sec
        self._dm = dm
        self._ises = None
        self._halo = halo.Halo(dm)

        # Compute entity class offsets
        self.dof_classes = [0, 0, 0, 0]
        for d in range(mesh._plex.getDimension()+1):
            ndofs = self._dofs_per_entity[d]
            for i in range(4):
                self.dof_classes[i] += ndofs * mesh._entity_classes[d, i]

        # Tell the DM about the layout of the global vector
        from firedrake.function import Function
        with Function(self).dat.vec_ro as v:
            self._dm.setGlobalVector(v.duplicate())

        self._node_count = self._global_numbering.getStorageSize()

        self.cell_node_list = mesh.create_cell_node_list(self._global_numbering,
                                                         self.fiat_element)

        if mesh._plex.getStratumSize("interior_facets", 1) > 0:
            self.interior_facet_node_list = \
                dmplex.get_facet_nodes(mesh.interior_facets.facet_cell,
                                       self.cell_node_list)
        else:
            self.interior_facet_node_list = np.array([], dtype=np.int32)

        if mesh._plex.getStratumSize("exterior_facets", 1) > 0:
            self.exterior_facet_node_list = \
                dmplex.get_facet_nodes(mesh.exterior_facets.facet_cell,
                                       self.cell_node_list)
        else:
            self.exterior_facet_node_list = np.array([], dtype=np.int32)

        # 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 = {}
Example #4
0
    def __new__(cls, mesh, element, name=None, shape=()):
        """
        :param mesh: :class:`MeshTopology` to build this space on
        :param element: :class:`ufl.FiniteElementBase` to build this space from
        :param name: user-defined name for this space
        :param shape: shape of a :class:`.VectorFunctionSpace` or :class:`.TensorFunctionSpace`
        """

        assert mesh.ufl_cell() == element.cell()

        self = super(FunctionSpaceBase, cls).__new__(cls, mesh, element, name,
                                                     shape)
        if self._initialized:
            return self

        self._mesh = mesh
        self._ufl_element = element
        self.name = name
        self._shape = shape

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

        entity_dofs = self.fiat_element.entity_dofs()
        dofs_per_entity = mesh.make_dofs_per_plex_entity(entity_dofs)

        self.extruded = bool(mesh.layers)
        self.offset = mesh.make_offset(entity_dofs,
                                       self.fiat_element.space_dimension())

        if mesh.layers:
            # Compute the top and bottom masks to identify boundary dofs
            #
            # Sorting the keys of the closure entity dofs, the whole cell
            # comes last [-1], before that the horizontal facet [-2], before
            # that vertical facets [-3]. We need the horizontal facets here.
            closure_dofs = self.fiat_element.entity_closure_dofs()
            b_mask = closure_dofs[sorted(closure_dofs.keys())[-2]][0]
            t_mask = closure_dofs[sorted(closure_dofs.keys())[-2]][1]
            self.bt_masks = {}
            self.bt_masks["topological"] = (b_mask, t_mask
                                            )  # conversion to tuple
            # Geometric facet dofs
            facet_dofs = horiz_facet_support_dofs(self.fiat_element)
            self.bt_masks["geometric"] = (facet_dofs[0], facet_dofs[1])
        else:
            self.bt_masks = None

        dm = PETSc.DMShell().create()
        dm.setAttr('__fs__', weakref.ref(self))
        dm.setPointSF(mesh._plex.getPointSF())
        # Create the PetscSection mapping topological entities to DoFs
        sec = mesh._plex.createSection([1],
                                       dofs_per_entity,
                                       perm=mesh._plex_renumbering)
        dm.setDefaultSection(sec)
        self._global_numbering = sec
        self._dm = dm
        self._ises = None
        self._halo = halo.Halo(dm)

        # Compute entity class offsets
        self.dof_classes = [0, 0, 0, 0]
        for d in range(mesh._plex.getDimension() + 1):
            ndofs = dofs_per_entity[d]
            for i in range(4):
                self.dof_classes[i] += ndofs * mesh._entity_classes[d, i]

        # Tell the DM about the layout of the global vector
        with self.make_dat().vec_ro as v:
            self._dm.setGlobalVector(v.duplicate())

        self._node_count = self._global_numbering.getStorageSize()

        self.cell_node_list = mesh.make_cell_node_list(self._global_numbering,
                                                       entity_dofs)

        if mesh._plex.getStratumSize("interior_facets", 1) > 0:
            self.interior_facet_node_list = \
                dmplex.get_facet_nodes(mesh.interior_facets.facet_cell,
                                       self.cell_node_list)
        else:
            self.interior_facet_node_list = np.array([], dtype=np.int32)

        if mesh._plex.getStratumSize("exterior_facets", 1) > 0:
            self.exterior_facet_node_list = \
                dmplex.get_facet_nodes(mesh.exterior_facets.facet_cell,
                                       self.cell_node_list)
        else:
            self.exterior_facet_node_list = np.array([], dtype=np.int32)

        # 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 = {}

        self._initialized = True
        return self
Example #5
0
    def __new__(cls, mesh, element, name=None, shape=()):
        """
        :param mesh: :class:`MeshTopology` to build this space on
        :param element: :class:`ufl.FiniteElementBase` to build this space from
        :param name: user-defined name for this space
        :param shape: shape of a :class:`.VectorFunctionSpace` or :class:`.TensorFunctionSpace`
        """

        assert mesh.ufl_cell() == element.cell()

        self = super(FunctionSpaceBase, cls).__new__(cls, mesh, element, name, shape)
        if self._initialized:
            return self

        self._mesh = mesh
        self._ufl_element = element
        self.name = name
        self._shape = shape

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

        entity_dofs = self.fiat_element.entity_dofs()
        dofs_per_entity = mesh.make_dofs_per_plex_entity(entity_dofs)

        self.extruded = bool(mesh.layers)
        self.offset = mesh.make_offset(entity_dofs,
                                       self.fiat_element.space_dimension())

        if mesh.layers:
            # Compute the top and bottom masks to identify boundary dofs
            #
            # Sorting the keys of the closure entity dofs, the whole cell
            # comes last [-1], before that the horizontal facet [-2], before
            # that vertical facets [-3]. We need the horizontal facets here.
            closure_dofs = self.fiat_element.entity_closure_dofs()
            b_mask = closure_dofs[sorted(closure_dofs.keys())[-2]][0]
            t_mask = closure_dofs[sorted(closure_dofs.keys())[-2]][1]
            self.bt_masks = {}
            self.bt_masks["topological"] = (b_mask, t_mask)  # conversion to tuple
            # Geometric facet dofs
            facet_dofs = horiz_facet_support_dofs(self.fiat_element)
            self.bt_masks["geometric"] = (facet_dofs[0], facet_dofs[1])
        else:
            self.bt_masks = None

        dm = PETSc.DMShell().create()
        dm.setAttr('__fs__', weakref.ref(self))
        dm.setPointSF(mesh._plex.getPointSF())
        # Create the PetscSection mapping topological entities to DoFs
        sec = mesh._plex.createSection([1], dofs_per_entity,
                                       perm=mesh._plex_renumbering)
        dm.setDefaultSection(sec)
        self._global_numbering = sec
        self._dm = dm
        self._ises = None
        self._halo = halo.Halo(dm)

        # Compute entity class offsets
        self.dof_classes = [0, 0, 0, 0]
        for d in range(mesh._plex.getDimension()+1):
            ndofs = dofs_per_entity[d]
            for i in range(4):
                self.dof_classes[i] += ndofs * mesh._entity_classes[d, i]

        # Tell the DM about the layout of the global vector
        with self.make_dat().vec_ro as v:
            self._dm.setGlobalVector(v.duplicate())

        self._node_count = self._global_numbering.getStorageSize()

        self.cell_node_list = mesh.make_cell_node_list(self._global_numbering,
                                                       entity_dofs)

        if mesh._plex.getStratumSize("interior_facets", 1) > 0:
            self.interior_facet_node_list = \
                dmplex.get_facet_nodes(mesh.interior_facets.facet_cell,
                                       self.cell_node_list)
        else:
            self.interior_facet_node_list = np.array([], dtype=np.int32)

        if mesh._plex.getStratumSize("exterior_facets", 1) > 0:
            self.exterior_facet_node_list = \
                dmplex.get_facet_nodes(mesh.exterior_facets.facet_cell,
                                       self.cell_node_list)
        else:
            self.exterior_facet_node_list = np.array([], dtype=np.int32)

        # 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 = {}

        self._initialized = True
        return self
def test_prism(prism_mesh, args, kwargs, horiz_expected, vert_expected):
    V = FunctionSpace(prism_mesh, *args, **kwargs)
    assert horiz_expected == horiz_facet_support_dofs(V.fiat_element)
    assert vert_expected == vert_facet_support_dofs(V.fiat_element)
Example #7
0
def test_quad(quad_mesh, args, kwargs, horiz_expected, vert_expected):
    V = FunctionSpace(quad_mesh, *args, **kwargs)
    assert horiz_expected == horiz_facet_support_dofs(V.fiat_element)
    assert vert_expected == vert_facet_support_dofs(V.fiat_element)