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)
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)
def exterior_facet_boundary_node_map(self, method): '''The :class:`pyop2.Map` from exterior facets to the nodes on those facets. Note that this differs from :meth:`exterior_facet_node_map` in that only surface nodes are referenced, not all nodes in cells touching the surface. :arg method: The method for determining boundary nodes. See :class:`~.bcs.DirichletBC`. ''' el = self.fiat_element dim = self._mesh.facet_dimension() if method == "topological": boundary_dofs = el.entity_closure_dofs()[dim] elif method == "geometric": if self.extruded: # This function is only called on extruded meshes when # asking for the nodes that live on the "vertical" # exterior facets. Hence we don't need to worry about # horiz_facet_support_dofs as well. boundary_dofs = vert_facet_support_dofs(el) else: boundary_dofs = facet_support_dofs(el) nodes_per_facet = \ len(boundary_dofs[0]) # HACK ALERT # The facet set does not have a halo associated with it, since # we only construct halos for DoF sets. Fortunately, this # loop is direct and we already have all the correct # information available locally. So We fake a set of the # correct size and carry out a direct loop facet_set = op2.Set(self._mesh.exterior_facets.set.total_size) fs_dat = op2.Dat(facet_set**el.space_dimension(), data=self.exterior_facet_node_map().values_with_halo) facet_dat = op2.Dat(facet_set**nodes_per_facet, dtype=np.int32) local_facet_nodes = np.array( [dofs for e, dofs in boundary_dofs.iteritems()]) # Helper function to turn the inner index of an array into c # array literals. c_array = lambda xs: "{"+", ".join(map(str, xs))+"}" body = ast.Block([ast.Decl("int", ast.Symbol("l_nodes", (len(el.get_reference_element().topology[dim]), nodes_per_facet)), init=ast.ArrayInit(c_array(map(c_array, local_facet_nodes))), qualifiers=["const"]), ast.For(ast.Decl("int", "n", 0), ast.Less("n", nodes_per_facet), ast.Incr("n", 1), ast.Assign(ast.Symbol("facet_nodes", ("n",)), ast.Symbol("cell_nodes", ("l_nodes[facet[0]][n]",)))) ]) kernel = op2.Kernel(ast.FunDecl("void", "create_bc_node_map", [ast.Decl("int*", "cell_nodes"), ast.Decl("int*", "facet_nodes"), ast.Decl("unsigned int*", "facet")], body), "create_bc_node_map") local_facet_dat = op2.Dat(facet_set ** self._mesh.exterior_facets._rank, self._mesh.exterior_facets.local_facet_dat.data_ro_with_halos, dtype=np.uintc) op2.par_loop(kernel, facet_set, fs_dat(op2.READ), facet_dat(op2.WRITE), local_facet_dat(op2.READ)) if isinstance(self._mesh, mesh_t.ExtrudedMesh): offset = self.offset[boundary_dofs[0]] else: offset = None return op2.Map(facet_set, self.node_set, nodes_per_facet, facet_dat.data_ro_with_halos, name="exterior_facet_boundary_node", offset=offset)
def exterior_facet_boundary_node_map(self, method): '''The :class:`pyop2.Map` from exterior facets to the nodes on those facets. Note that this differs from :meth:`exterior_facet_node_map` in that only surface nodes are referenced, not all nodes in cells touching the surface. :arg method: The method for determining boundary nodes. See :class:`~.bcs.DirichletBC`. ''' el = self.fiat_element dim = self._mesh.facet_dimension() if method == "topological": boundary_dofs = el.entity_closure_dofs()[dim] elif method == "geometric": if self.extruded: # This function is only called on extruded meshes when # asking for the nodes that live on the "vertical" # exterior facets. Hence we don't need to worry about # horiz_facet_support_dofs as well. boundary_dofs = vert_facet_support_dofs(el) else: boundary_dofs = facet_support_dofs(el) nodes_per_facet = \ len(boundary_dofs[0]) # HACK ALERT # The facet set does not have a halo associated with it, since # we only construct halos for DoF sets. Fortunately, this # loop is direct and we already have all the correct # information available locally. So We fake a set of the # correct size and carry out a direct loop facet_set = op2.Set(self._mesh.exterior_facets.set.total_size) fs_dat = op2.Dat(facet_set**el.space_dimension(), data=self.exterior_facet_node_map().values_with_halo) facet_dat = op2.Dat(facet_set**nodes_per_facet, dtype=np.int32) local_facet_nodes = np.array( [dofs for e, dofs in boundary_dofs.iteritems()]) # Helper function to turn the inner index of an array into c # array literals. c_array = lambda xs: "{" + ", ".join(map(str, xs)) + "}" body = ast.Block([ ast.Decl("int", ast.Symbol("l_nodes", (len(el.get_reference_element().topology[dim]), nodes_per_facet)), init=ast.ArrayInit( c_array(map(c_array, local_facet_nodes))), qualifiers=["const"]), ast.For( ast.Decl("int", "n", 0), ast.Less("n", nodes_per_facet), ast.Incr("n", 1), ast.Assign( ast.Symbol("facet_nodes", ("n", )), ast.Symbol("cell_nodes", ("l_nodes[facet[0]][n]", )))) ]) kernel = op2.Kernel( ast.FunDecl("void", "create_bc_node_map", [ ast.Decl("int*", "cell_nodes"), ast.Decl("int*", "facet_nodes"), ast.Decl("unsigned int*", "facet") ], body), "create_bc_node_map") local_facet_dat = op2.Dat( facet_set**self._mesh.exterior_facets._rank, self._mesh.exterior_facets.local_facet_dat.data_ro_with_halos, dtype=np.uintc) op2.par_loop(kernel, facet_set, fs_dat(op2.READ), facet_dat(op2.WRITE), local_facet_dat(op2.READ)) if isinstance(self._mesh.topology, mesh_t.ExtrudedMeshTopology): offset = self.offset[boundary_dofs[0]] else: offset = None return op2.Map(facet_set, self.node_set, nodes_per_facet, facet_dat.data_ro_with_halos, name="exterior_facet_boundary_node", offset=offset)
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)
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)