Beispiel #1
0
    def _setup_vertex_dofs(self):
        """
        Setup vertex DOF connectivity.
        """
        if self.node_desc.vertex is None:
            return 0, None

        region = self.region

        cmesh = self.domain.cmesh
        conn, offsets = cmesh.get_incident(0,
                                           region.cells,
                                           region.tdim,
                                           ret_offsets=True)

        vertices = nm.unique(conn)
        remap = prepare_remap(vertices, region.n_v_max)
        n_dof = vertices.shape[0]

        aux = nm.unique(nm.diff(offsets))
        assert_(len(aux) == 1, 'region with multiple reference geometries!')
        offset = aux[0]

        # Remap vertex node connectivity to field-local numbering.
        aux = conn.reshape((-1, offset)).astype(nm.int32)
        self.econn[:, :offset] = nm.take(remap, aux)

        return n_dof, remap
Beispiel #2
0
    def _setup_global_base(self):
        """
        Setup global DOF/base function indices and connectivity of the field.
        """
        self._setup_facet_orientations()

        self._init_econn()

        ii = self.region.get_cells()
        self.bubble_remap = prepare_remap(ii, self.domain.cmesh.n_el)

        n_dof = nm.prod(self.econn.shape)
        all_dofs = nm.arange(n_dof, dtype=nm.int32)
        all_dofs.shape = self.econn.shape

        self.econn[:] = all_dofs

        self.n_nod = n_dof

        self.n_bubble_dof = n_dof
        self.bubble_dofs = all_dofs

        self.n_vertex_dof = self.n_edge_dof = self.n_face_dof = 0

        self._setup_esurface()
Beispiel #3
0
    def _setup_vertex_dofs(self):
        """
        Setup vertex DOF connectivity.
        """
        if self.node_desc.vertex is None:
            return 0, None

        region = self.region

        vertices = region.get_vertices_of_cells()
        remap = prepare_remap(vertices, region.n_v_max)
        n_dof = vertices.shape[0]

        ##
        # Remap vertex node connectivity to field-local numbering.
        for ig, ap in self.aps.iteritems():
            group = self.domain.groups[ig]
            offset = group.shape.n_ep
            cells = region.get_cells(ig)
            ap.econn[:,:offset] = nm.take(remap,
                                          nm.take(group.conn,
                                                  cells.astype(nm.int32),
                                                  axis=0))

        return n_dof, remap
Beispiel #4
0
    def _setup_vertex_dofs(self):
        """
        Setup vertex DOF connectivity.
        """
        if self.node_desc.vertex is None:
            return 0, None

        region = self.region

        vertices = region.get_vertices_of_cells()
        remap = prepare_remap(vertices, region.n_v_max)
        n_dof = vertices.shape[0]

        ##
        # Remap vertex node connectivity to field-local numbering.
        for ig, ap in self.aps.iteritems():
            group = self.domain.groups[ig]
            offset = group.shape.n_ep
            cells = region.get_cells(ig)
            ap.econn[:,:offset] = nm.take(remap,
                                          nm.take(group.conn,
                                                  cells.astype(nm.int32),
                                                  axis=0))

        return n_dof, remap
Beispiel #5
0
    def _setup_bubble_dofs(self):
        """
        Setup bubble DOF connectivity.
        """
        if self.node_desc.bubble is None:
            return 0, None, None

        offset = self.n_vertex_dof + self.n_edge_dof + self.n_face_dof
        n_dof = 0
        n_dof_per_cell = self.node_desc.bubble.shape[0]
        all_dofs = {}
        remaps = {}
        for ig, ap in self.aps.iteritems():
            ii = self.region.get_cells(ig)
            n_cell = ii.shape[0]
            nd = n_dof_per_cell * n_cell

            group = self.domain.groups[ig]
            remaps[ig] = prepare_remap(ii, group.shape.n_el)

            aux = nm.arange(offset + n_dof, offset + n_dof + nd,
                            dtype=nm.int32)
            aux.shape = (n_cell, n_dof_per_cell)
            iep = self.node_desc.bubble[0]
            ap.econn[:,iep:] = aux
            all_dofs[ig] = aux

            n_dof += nd

        return n_dof, all_dofs, remaps
Beispiel #6
0
    def _setup_global_base(self):
        """
        Setup global DOF/base function indices and connectivity of the field.
        """
        self._setup_facet_orientations()

        self._init_econn()

        ii = self.region.get_cells()
        self.bubble_remap = prepare_remap(ii, self.domain.cmesh.n_el)

        n_dof = nm.prod(self.econn.shape)
        all_dofs = nm.arange(n_dof, dtype=nm.int32)
        all_dofs.shape = self.econn.shape

        self.econn[:] = all_dofs

        self.n_nod = n_dof

        self.n_bubble_dof = n_dof
        self.bubble_dofs = all_dofs

        self.n_vertex_dof = self.n_edge_dof = self.n_face_dof = 0

        self._setup_esurface()
Beispiel #7
0
    def _setup_bubble_dofs(self):
        """
        Setup bubble DOF connectivity.
        """
        if self.node_desc.bubble is None:
            return 0, None, None

        offset = self.n_vertex_dof + self.n_edge_dof + self.n_face_dof
        n_dof = 0
        n_dof_per_cell = self.node_desc.bubble.shape[0]
        all_dofs = {}
        remaps = {}
        for ig, ap in self.aps.iteritems():
            ii = self.region.get_cells(ig)
            n_cell = ii.shape[0]
            nd = n_dof_per_cell * n_cell

            group = self.domain.groups[ig]
            remaps[ig] = prepare_remap(ii, group.shape.n_el)

            aux = nm.arange(offset + n_dof,
                            offset + n_dof + nd,
                            dtype=nm.int32)
            aux.shape = (n_cell, n_dof_per_cell)
            iep = self.node_desc.bubble[0]
            ap.econn[:, iep:] = aux
            all_dofs[ig] = aux

            n_dof += nd

        return n_dof, all_dofs, remaps
Beispiel #8
0
    def _setup_global_base( self ):
        """
        Setup global DOF/base function indices and connectivity of the field.
        """
        self._setup_facet_orientations()

        self._init_econn()

        n_dof = 0
        all_dofs = {}
        remaps = {}
        for ig, ap in self.aps.iteritems():
            ii = self.region.get_cells(ig)
            nd = nm.prod(ap.econn.shape)

            group = self.domain.groups[ig]
            remaps[ig] = prepare_remap(ii, group.shape.n_el)

            aux = nm.arange(n_dof, n_dof + nd, dtype=nm.int32)
            aux.shape = ap.econn.shape

            ap.econn[:] = aux
            all_dofs[ig] = aux

            n_dof += nd

        self.n_nod = n_dof

        self.n_bubble_dof = n_dof
        self.bubble_dofs = all_dofs
        self.bubble_remaps = remaps

        self.n_vertex_dof = self.n_edge_dof = self.n_face_dof = 0

        self._setup_esurface()
Beispiel #9
0
    def _setup_vertex_dofs(self):
        """
        Setup vertex DOF connectivity.
        """
        if self.node_desc.vertex is None:
            return 0, None

        region = self.region

        cmesh = self.domain.cmesh
        conn, offsets = cmesh.get_incident(0, region.cells, region.tdim,
                                           ret_offsets=True)

        vertices = nm.unique(conn)
        remap = prepare_remap(vertices, region.n_v_max)
        n_dof = vertices.shape[0]

        aux = nm.unique(nm.diff(offsets))
        assert_(len(aux) == 1, 'region with multiple reference geometries!')
        offset = aux[0]


        # Remap vertex node connectivity to field-local numbering.
        aux = conn.reshape((-1, offset)).astype(nm.int32)
        self.econn[:, :offset] = nm.take(remap, aux)

        return n_dof, remap
Beispiel #10
0
    def _setup_global_base(self):
        """
        Setup global DOF/base function indices and connectivity of the field.
        """
        self._setup_facet_orientations()

        self._init_econn()

        n_dof = 0
        all_dofs = {}
        remaps = {}
        for ig, ap in self.aps.iteritems():
            ii = self.region.get_cells(ig)
            nd = nm.prod(ap.econn.shape)

            group = self.domain.groups[ig]
            remaps[ig] = prepare_remap(ii, group.shape.n_el)

            aux = nm.arange(n_dof, n_dof + nd, dtype=nm.int32)
            aux.shape = ap.econn.shape

            ap.econn[:] = aux
            all_dofs[ig] = aux

            n_dof += nd

        self.n_nod = n_dof

        self.n_bubble_dof = n_dof
        self.bubble_dofs = all_dofs
        self.bubble_remaps = remaps

        self.n_vertex_dof = self.n_edge_dof = self.n_face_dof = 0

        self._setup_esurface()
Beispiel #11
0
    def __init__(self, name, nurbs, bmesh, regions=None, **kwargs):
        """
        Create an IGA domain.

        Parameters
        ----------
        name : str
            The domain name.
        """
        Domain.__init__(self, name, nurbs=nurbs, bmesh=bmesh, regions=regions,
                        **kwargs)
        from sfepy.discrete.fem.geometry_element import create_geometry_elements
        from sfepy.discrete.fem import Mesh
        from sfepy.discrete.fem.extmods.cmesh import CMesh
        from sfepy.discrete.fem.utils import prepare_remap

        ac = nm.ascontiguousarray
        self.nurbs.cs = [ac(nm.array(cc, dtype=nm.float64)[:, None, ...])
                         for cc in self.nurbs.cs]

        self.nurbs.degrees = self.nurbs.degrees.astype(nm.int32)

        self.facets = iga.get_bezier_element_entities(nurbs.degrees)

        tconn = iga.get_bezier_topology(bmesh.conn, nurbs.degrees)
        itc = nm.unique(tconn)

        remap = prepare_remap(itc, bmesh.conn.max() + 1)

        ltcoors = bmesh.cps[itc]
        ltconn = remap[tconn]

        n_nod, dim = ltcoors.shape
        n_el = ltconn.shape[0]
        self.shape = Struct(n_nod=n_nod, dim=dim, tdim=0, n_el=n_el, n_gr=1)

        desc = '%d_%d' % (dim, 2**dim)
        mat_id = nm.zeros(ltconn.shape[0], dtype=nm.int32)
        self.mesh = Mesh.from_data(self.name + '_topo', ltcoors, None, [ltconn],
                                   [mat_id], [desc])

        self.cmesh = CMesh.from_mesh(self.mesh)
        gels = create_geometry_elements()
        self.cmesh.set_local_entities(gels)
        self.cmesh.setup_entities()

        self.shape.tdim = self.cmesh.tdim

        self.gel = gels[desc]

        if regions is not None:
            self.vertex_set_bcs = {}
            for key, val in self.regions.iteritems():
                self.vertex_set_bcs[key] = remap[val]

        self.cell_offsets = {0 : 0}

        self.reset_regions()
Beispiel #12
0
    def __init__(self, name, region, efaces, volume_econn, volume_region=None):
        """nodes[leconn] == econn"""
        """nodes are sorted by node number -> same order as region.vertices"""
        self.name = get_default(name, 'surface_data_%s' % region.name)

        face_indices = region.get_facet_indices()

        faces = efaces[face_indices[:,1]]
        if faces.size == 0 and not region.is_empty:
            raise ValueError('region with no faces! (%s)' % region.name)

        if volume_region is None:
            ii = face_indices[:, 0]

        else:
            ii = volume_region.get_cell_indices(face_indices[:, 0])

        try:
            ee = volume_econn[ii]

        except:
            raise ValueError('missing region face indices! (%s)'
                             % region.name)

        econn = nm.empty(faces.shape, dtype=nm.int32)
        for ir, face in enumerate( faces ):
            econn[ir] = ee[ir,face]

        nodes = nm.unique(econn)
        if len(nodes):
            remap = prepare_remap(nodes, nodes.max() + 1)
            leconn = remap[econn].copy()

        else:
            leconn = econn.copy()

        n_fa, n_fp = face_indices.shape[0], faces.shape[1]
        face_type = 's%d' % n_fp

        # Store bkey in SurfaceData, so that base function can be
        # queried later.
        bkey = 'b%s' % face_type[1:]

        self.econn = econn
        self.fis = nm.ascontiguousarray(face_indices.astype(nm.int32))
        self.n_fa, self.n_fp = n_fa, n_fp
        self.nodes = nodes
        self.leconn = leconn
        self.face_type = face_type
        self.bkey = bkey
        self.meconn = self.mleconn = None

        if self.n_fp <= 4:
            self.ori_map, _, _ = build_orientation_map(self.n_fp)

        else:
            self.ori_map = None
Beispiel #13
0
    def __init__(self, name, nurbs, bmesh, regions=None, **kwargs):
        """
        Create an IGA domain.

        Parameters
        ----------
        name : str
            The domain name.
        """
        Domain.__init__(self,
                        name,
                        nurbs=nurbs,
                        bmesh=bmesh,
                        regions=regions,
                        **kwargs)
        from sfepy.discrete.fem.geometry_element import create_geometry_elements
        from sfepy.discrete.fem import Mesh
        from sfepy.discrete.fem.utils import prepare_remap

        tconn = iga.get_bezier_topology(bmesh.conn, nurbs.degrees)
        itc = nm.unique(tconn)

        remap = prepare_remap(itc, bmesh.conn.max() + 1)

        ltcoors = bmesh.cps[itc]
        ltconn = remap[tconn]

        n_nod, dim = ltcoors.shape
        n_el = ltconn.shape[0]
        self.shape = Struct(n_nod=n_nod, dim=dim, tdim=0, n_el=n_el)

        desc = '%d_%d' % (dim, bmesh.conn.shape[1])
        mat_id = nm.zeros(bmesh.conn.shape[0], dtype=nm.int32)
        eval_mesh = Mesh.from_data(self.name + '_eval', nurbs.cps, None,
                                   [nurbs.conn], [mat_id], [desc])
        self.eval_mesh = eval_mesh

        desc = '%d_%d' % (dim, 2**dim)
        mat_id = nm.zeros(ltconn.shape[0], dtype=nm.int32)
        self.mesh = Mesh.from_data(self.name + '_topo', ltcoors, None,
                                   [ltconn], [mat_id], [desc])

        self.cmesh = self.mesh.cmesh
        gels = create_geometry_elements()
        self.cmesh.set_local_entities(gels)
        self.cmesh.setup_entities()

        self.shape.tdim = self.cmesh.tdim

        self.gel = gels[desc]

        if regions is not None:
            self.vertex_set_bcs = {}
            for key, val in six.iteritems(self.regions):
                self.vertex_set_bcs[key] = remap[val]

        self.reset_regions()
Beispiel #14
0
    def _setup_facet_dofs(self, dim, facet_desc, facet_perms, offset):
        """
        Helper function to setup facet DOF connectivity, works for both
        edges and faces.
        """
        facet_desc = nm.array(facet_desc)
        n_dof_per_facet = facet_desc.shape[1]

        cmesh = self.domain.cmesh

        facets = self.region.entities[dim]
        ii = nm.arange(facets.shape[0], dtype=nm.int32)
        all_dofs = offset + expand_nodes_to_dofs(ii, n_dof_per_facet)

        # Prepare global facet id remapping to field-local numbering.
        remap = prepare_remap(facets, cmesh.num[dim])

        cconn = self.region.domain.cmesh.get_conn(self.region.tdim, dim)
        offs = cconn.offsets

        n_f = self.gel.edges.shape[0] if dim == 1 else self.gel.faces.shape[0]

        oris = cmesh.get_orientations(dim)

        gcells = self.region.get_cells()
        n_el = gcells.shape[0]

        # Elements of facets.
        iel = nm.arange(n_el, dtype=nm.int32).repeat(n_f)
        ies = nm.tile(nm.arange(n_f, dtype=nm.int32), n_el)

        aux = offs[gcells][:, None] + ies.reshape((n_el, n_f))

        indices = cconn.indices[aux]
        facets_of_cells = remap[indices].ravel()

        ori = oris[aux].ravel()
        perms = facet_perms[ori]

        # Define global facet dof numbers.
        gdofs = offset + expand_nodes_to_dofs(facets_of_cells,
                                              n_dof_per_facet)

        # DOF columns in econn for each facet.
        iep = facet_desc[ies]

        iaux = nm.arange(gdofs.shape[0], dtype=nm.int32)
        self.econn[iel[:, None], iep] = gdofs[iaux[:, None], perms]

        n_dof = n_dof_per_facet * facets.shape[0]
        assert_(n_dof == nm.prod(all_dofs.shape))

        return n_dof, all_dofs, remap
Beispiel #15
0
    def _setup_facet_dofs(self, dim, facet_desc, facet_perms, offset):
        """
        Helper function to setup facet DOF connectivity, works for both
        edges and faces.
        """
        facet_desc = nm.array(facet_desc)
        n_dof_per_facet = facet_desc.shape[1]

        cmesh = self.domain.cmesh

        facets = self.region.entities[dim]
        ii = nm.arange(facets.shape[0], dtype=nm.int32)
        all_dofs = offset + expand_nodes_to_dofs(ii, n_dof_per_facet)

        # Prepare global facet id remapping to field-local numbering.
        remap = prepare_remap(facets, cmesh.num[dim])

        cconn = self.region.domain.cmesh.get_conn(self.region.tdim, dim)
        offs = cconn.offsets

        n_f = self.gel.edges.shape[0] if dim == 1 else self.gel.faces.shape[0]

        oris = cmesh.get_orientations(dim)

        gcells = self.region.get_cells()
        n_el = gcells.shape[0]

        # Elements of facets.
        iel = nm.arange(n_el, dtype=nm.int32).repeat(n_f)
        ies = nm.tile(nm.arange(n_f, dtype=nm.int32), n_el)

        aux = offs[gcells][:, None] + ies.reshape((n_el, n_f))

        indices = cconn.indices[aux]
        facets_of_cells = remap[indices].ravel()

        ori = oris[aux].ravel()
        perms = facet_perms[ori]

        # Define global facet dof numbers.
        gdofs = offset + expand_nodes_to_dofs(facets_of_cells,
                                              n_dof_per_facet)

        # DOF columns in econn for each facet.
        iep = facet_desc[ies]

        iaux = nm.arange(gdofs.shape[0], dtype=nm.int32)
        self.ap.econn[iel[:, None], iep] = gdofs[iaux[:, None], perms]

        n_dof = n_dof_per_facet * facets.shape[0]
        assert_(n_dof == nm.prod(all_dofs.shape))

        return n_dof, all_dofs, remap
Beispiel #16
0
    def __init__(self, name, nurbs, bmesh, regions=None, **kwargs):
        """
        Create an IGA domain.

        Parameters
        ----------
        name : str
            The domain name.
        """
        Domain.__init__(self, name, nurbs=nurbs, bmesh=bmesh, regions=regions,
                        **kwargs)
        from sfepy.discrete.fem.geometry_element import create_geometry_elements
        from sfepy.discrete.fem import Mesh
        from sfepy.discrete.fem.utils import prepare_remap

        tconn = iga.get_bezier_topology(bmesh.conn, nurbs.degrees)
        itc = nm.unique(tconn)

        remap = prepare_remap(itc, bmesh.conn.max() + 1)

        ltcoors = bmesh.cps[itc]
        ltconn = remap[tconn]

        n_nod, dim = ltcoors.shape
        n_el = ltconn.shape[0]
        self.shape = Struct(n_nod=n_nod, dim=dim, tdim=0, n_el=n_el)

        desc = '%d_%d' % (dim, bmesh.conn.shape[1])
        mat_id = nm.zeros(bmesh.conn.shape[0], dtype=nm.int32)
        eval_mesh = Mesh.from_data(self.name + '_eval', nurbs.cps, None,
                                   [nurbs.conn], [mat_id], [desc])
        self.eval_mesh = eval_mesh

        desc = '%d_%d' % (dim, 2**dim)
        mat_id = nm.zeros(ltconn.shape[0], dtype=nm.int32)
        self.mesh = Mesh.from_data(self.name + '_topo', ltcoors, None, [ltconn],
                                   [mat_id], [desc])

        self.cmesh = self.mesh.cmesh
        gels = create_geometry_elements()
        self.cmesh.set_local_entities(gels)
        self.cmesh.setup_entities()

        self.shape.tdim = self.cmesh.tdim

        self.gel = gels[desc]

        if regions is not None:
            self.vertex_set_bcs = {}
            for key, val in self.regions.iteritems():
                self.vertex_set_bcs[key] = remap[val]

        self.reset_regions()
Beispiel #17
0
    def setup_mirror_connectivity(self, region, mirror_name):
        """
        Setup mirror surface connectivity required to integrate over a
        mirror region.

        1. Get orientation of the faces:
           a) for own elements -> ooris
           b) for mirror elements -> moris

        2. orientation -> permutation.
        """
        mregion = region.get_mirror_region(mirror_name)

        oo = self.ori_map
        ori_map = nm.zeros((nm.max(list(oo.keys())) + 1, self.n_fp),
                           dtype=nm.int32)
        ori_map[list(oo.keys())] = nm.array([ii[1] for ii in oo.values()])

        conn = region.domain.cmesh.get_conn_as_graph(region.dim,
                                                     region.dim - 1)
        oris = region.domain.cmesh.facet_oris

        econn = self.econn
        ofis = region.get_facet_indices()
        if mirror_name in region.mirror_maps\
            and region.mirror_maps[mirror_name] is not None:
            mirror_map = region.mirror_maps[mirror_name]
            ofis = ofis[mirror_map]
            econn = econn[mirror_map]
        ooris = oris[conn.indptr[ofis[:, 0]] + ofis[:, 1]]
        mfis = mregion.get_facet_indices()
        moris = oris[conn.indptr[mfis[:, 0]] + mfis[:, 1]]

        omap = ori_map[ooris]
        mmap = ori_map[moris]

        n_el, n_ep = self.econn.shape
        ii = nm.repeat(nm.arange(n_el)[:, None], n_ep, 1)
        self.meconn = nm.empty_like(self.econn)
        self.meconn[ii, omap] = econn[ii, mmap]

        nodes = nm.unique(self.meconn)
        remap = prepare_remap(nodes, nodes.max() + 1)
        self.mleconn = remap[self.meconn].copy()
Beispiel #18
0
    def _setup_vertex_dofs(self):
        """
        Setup vertex DOF connectivity.
        """
        if self.node_desc.vertex is None:
            return 0, None

        region = self.region

        remap = prepare_remap(region.vertices, region.n_v_max)
        n_dof = region.vertices.shape[0]

        # Remap vertex node connectivity to field-local numbering.
        conn, gel = self.domain.get_conn(ret_gel=True)
        faces = gel.get_surface_entities()
        aux = FESurface('aux', region, faces, conn)
        self.econn[:, :aux.n_fp] = aux.leconn
        self.surface_data[region.name] = aux

        return n_dof, remap
Beispiel #19
0
    def _setup_vertex_dofs(self):
        """
        Setup vertex DOF connectivity.
        """
        if self.node_desc.vertex is None:
            return 0, None

        region = self.region

        remap = prepare_remap(region.vertices, region.n_v_max)
        n_dof = region.vertices.shape[0]

        # Remap vertex node connectivity to field-local numbering.
        conn, gel = self.domain.get_conn(ret_gel=True)
        faces = gel.get_surface_entities()
        aux = FESurface('aux', region, faces, conn)
        self.econn[:, :aux.n_fp] = aux.leconn
        self.surface_data[region.name] = aux

        return n_dof, remap
Beispiel #20
0
    def get_econn(self,
                  conn_type,
                  region,
                  is_trace=False,
                  integration=None,
                  local=False):
        """
        Get DOF connectivity of the given type in the given region.
        """
        ct = conn_type.type if isinstance(conn_type, Struct) else conn_type

        nconn = self.nurbs.conn

        if ct == 'volume':
            if region.name == self.region.name:
                conn = nconn

            else:
                cells = region.get_cells(true_cells_only=True)
                conn = nm.take(nconn, cells.astype(nm.int32), axis=0)

        elif ct == 'surface':
            fis = region.get_facet_indices()
            tdim = region.kind_tdim
            facets = self._get_facets(tdim)

            conn = []
            for ii, fi in enumerate(fis):
                conn.append(nconn[fi[0], facets[fi[1]]])

            if local:
                from sfepy.discrete.fem.utils import prepare_remap

                nods = nm.unique(conn)
                remap = prepare_remap(nods, nods.max() + 1)
                conn = [remap[ii] for ii in conn]

        else:
            raise ValueError('unsupported connectivity type! (%s)' % ct)

        return conn
Beispiel #21
0
    def _setup_bubble_dofs(self):
        """
        Setup bubble DOF connectivity.
        """
        if self.node_desc.bubble is None:
            return 0, None, None

        offset = self.n_vertex_dof + self.n_edge_dof + self.n_face_dof
        n_dof_per_cell = self.node_desc.bubble.shape[0]

        ii = self.region.get_cells()
        remap = prepare_remap(ii, self.domain.cmesh.n_el)

        n_cell = ii.shape[0]
        n_dof = n_dof_per_cell * n_cell

        all_dofs = nm.arange(offset, offset + n_dof, dtype=nm.int32)
        all_dofs.shape = (n_cell, n_dof_per_cell)
        iep = self.node_desc.bubble[0]
        self.econn[:,iep:] = all_dofs

        return n_dof, all_dofs, remap
Beispiel #22
0
    def _setup_vertex_dofs(self):
        """
        Setup vertex DOF connectivity.
        """
        if self.node_desc.vertex is None:
            return 0, None

        region = self.region

        remap = prepare_remap(region.vertices, region.n_v_max)
        n_dof = region.vertices.shape[0]

        ##
        # Remap vertex node connectivity to field-local numbering.
        for ig, ap in self.aps.iteritems():
            group = self.domain.groups[ig]
            faces = group.gel.get_surface_entities()
            aux = FESurface('aux', region, faces, group.conn, ig)
            ap.econn[:,:aux.n_fp] = aux.leconn
            ap.surface_data[region.name] = aux

        return n_dof, remap
Beispiel #23
0
    def _setup_vertex_dofs(self):
        """
        Setup vertex DOF connectivity.
        """
        if self.node_desc.vertex is None:
            return 0, None

        region = self.region

        remap = prepare_remap(region.vertices, region.n_v_max)
        n_dof = region.vertices.shape[0]

        ##
        # Remap vertex node connectivity to field-local numbering.
        for ig, ap in self.aps.iteritems():
            group = self.domain.groups[ig]
            faces = group.gel.get_surface_entities()
            aux = FESurface('aux', region, faces, group.conn, ig)
            ap.econn[:,:aux.n_fp] = aux.leconn
            ap.surface_data[region.name] = aux

        return n_dof, remap
Beispiel #24
0
    def _setup_bubble_dofs(self):
        """
        Setup bubble DOF connectivity.
        """
        if self.node_desc.bubble is None:
            return 0, None, None

        offset = self.n_vertex_dof + self.n_edge_dof + self.n_face_dof
        n_dof_per_cell = self.node_desc.bubble.shape[0]

        ii = self.region.get_cells()
        remap = prepare_remap(ii, self.domain.cmesh.n_el)

        n_cell = ii.shape[0]
        n_dof = n_dof_per_cell * n_cell

        all_dofs = nm.arange(offset, offset + n_dof, dtype=nm.int32)
        all_dofs.shape = (n_cell, n_dof_per_cell)
        iep = self.node_desc.bubble[0]
        self.econn[:, iep:] = all_dofs

        return n_dof, all_dofs, remap
Beispiel #25
0
    def setup_mirror_connectivity(self, region):
        """
        Setup mirror surface connectivity required to integrate over a
        mirror region.

        1. Get orientation of the faces:
           a) for elements in group ig -> ooris (own)
           b) for elements in group mig -> moris (mirror)

        2. orientation -> permutation.
        """
        mregion, ig_map, ig_map_i = region.get_mirror_region()
        mig = ig_map_i[self.ig]

        oo = self.ori_map
        ori_map = nm.zeros((nm.max(oo.keys()) + 1, self.n_fp), dtype=nm.int32)
        ori_map[oo.keys()] = nm.array([ii[1] for ii in oo.values()])

        conn = region.domain.cmesh.get_conn_as_graph(region.dim,
                                                     region.dim - 1)
        oris = region.domain.cmesh.facet_oris

        ofis = region.get_facet_indices(self.ig, offset=False)
        ooris = oris[conn.indptr[ofis[:, 0]] + ofis[:, 1]]
        mfis = mregion.get_facet_indices(mig, offset=False)
        moris = oris[conn.indptr[mfis[:, 0]] + mfis[:, 1]]

        omap = ori_map[ooris]
        mmap = ori_map[moris]

        n_el, n_ep = self.econn.shape
        ii = nm.repeat(nm.arange(n_el)[:, None], n_ep, 1)
        self.meconn = nm.empty_like(self.econn)
        self.meconn[ii, omap] = self.econn[ii, mmap]

        nodes = nm.unique(self.meconn)
        remap = prepare_remap(nodes, nodes.max() + 1)
        self.mleconn = remap[self.meconn].copy()
Beispiel #26
0
    def setup_mirror_connectivity(self, region):
        """
        Setup mirror surface connectivity required to integrate over a
        mirror region.

        1. Get orientation of the faces:
           a) for elements in group ig -> ooris (own)
           b) for elements in group mig -> moris (mirror)

        2. orientation -> permutation.
        """
        mregion, ig_map, ig_map_i = region.get_mirror_region()
        mig = ig_map_i[self.ig]

        oo = self.ori_map
        ori_map = nm.zeros((nm.max(oo.keys()) + 1, self.n_fp), dtype=nm.int32)
        ori_map[oo.keys()] = nm.array([ii[1] for ii in oo.values()])

        conn = region.domain.cmesh.get_conn_as_graph(region.dim, region.dim - 1)
        oris = region.domain.cmesh.facet_oris

        ofis = region.get_facet_indices(self.ig, offset=False)
        ooris = oris[conn.indptr[ofis[:, 0]] + ofis[:, 1]]
        mfis = mregion.get_facet_indices(mig, offset=False)
        moris = oris[conn.indptr[mfis[:, 0]] + mfis[:, 1]]

        omap = ori_map[ooris]
        mmap = ori_map[moris]

        n_el, n_ep = self.econn.shape
        ii = nm.repeat(nm.arange(n_el)[:, None], n_ep, 1)
        self.meconn = nm.empty_like(self.econn)
        self.meconn[ii, omap] = self.econn[ii, mmap]

        nodes = nm.unique(self.meconn)
        remap = prepare_remap(nodes, nodes.max() + 1)
        self.mleconn = remap[self.meconn].copy()
Beispiel #27
0
    def _setup_facet_dofs(self, dim, facet_desc, offset):
        """
        Helper function to setup facet DOF connectivity, works for both
        edges and faces.
        """
        facet_desc = nm.array(facet_desc)
        n_dof_per_facet = facet_desc.shape[1]

        cmesh = self.domain.cmesh

        facets = self.region.entities[dim]
        ii = nm.arange(facets.shape[0], dtype=nm.int32)
        all_dofs = offset + expand_nodes_to_dofs(ii, n_dof_per_facet)

        # Prepare global facet id remapping to field-local numbering.
        remap = prepare_remap(facets, cmesh.num[dim])

        cconn = self.region.domain.cmesh.get_conn(self.region.tdim, dim)
        offs = cconn.offsets

        n_f = self.gel.edges.shape[0] if dim == 1 else self.gel.faces.shape[0]
        n_fp = 2 if dim == 1 else self.gel.surface_facet.n_vertex

        oris = cmesh.get_orientations(dim)
        ap = self.ap

        gcells = self.region.get_cells()
        n_el = gcells.shape[0]

        # Elements of facets.
        iel = nm.arange(n_el, dtype=nm.int32).repeat(n_f)
        ies = nm.tile(nm.arange(n_f, dtype=nm.int32), n_el)

        aux = offs[gcells][:, None] + ies.reshape((n_el, n_f))

        indices = cconn.indices[aux]
        facets_of_cells = remap[indices].ravel()

        # Define global facet dof numbers.
        gdofs = offset + expand_nodes_to_dofs(facets_of_cells,
                                              n_dof_per_facet)

        # DOF columns in econn for each facet (repeating same values for
        # each element.
        iep = facet_desc[ies]

        ap.econn[iel[:, None], iep] = gdofs

        ori = oris[aux].ravel()

        if (n_fp == 2) and (ap.interp.gel.name in ['2_4', '3_8']):
            tp_edges = ap.interp.gel.edges
            ecs = ap.interp.gel.coors[tp_edges]
            # True = positive, False = negative edge orientation w.r.t.
            # reference tensor product axes.
            tp_edge_ori = (nm.diff(ecs, axis=1).sum(axis=2) > 0).squeeze()
            aux = nm.tile(tp_edge_ori, n_el)
            ori = nm.where(aux, ori, 1 - ori)

        if n_fp == 2: # Edges.
            # ori == 1 means the basis has to be multiplied by -1.
            ps = ap.interp.poly_spaces['v']
            orders = ps.node_orders
            eori = nm.repeat(ori[:, None], n_dof_per_facet, 1)
            eoo = orders[iep] % 2 # Odd orders.
            ap.ori[iel[:, None], iep] = eori * eoo

        elif n_fp == 3: # Triangular faces.
            raise NotImplementedError

        else: # Quadrilateral faces.
            # ori encoding in 3 bits:
            # 0: axis swap, 1: axis 1 sign, 2: axis 2 sign
            # 0 = + or False, 1 = - or True
            # 63 -> 000 = 0
            #  0 -> 001 = 1
            # 30 -> 010 = 2
            # 33 -> 011 = 3
            # 11 -> 100 = 4
            #  7 -> 101 = 5
            # 52 -> 110 = 6
            # 56 -> 111 = 7
            # Special cases:
            # Both orders same and even -> 000
            # Both orders same and odd -> 0??
            # Bits 1, 2 are multiplied by (swapped) axial order % 2.
            new = nm.repeat(nm.arange(8, dtype=nm.int32), 3)
            translate = prepare_translate([31, 59, 63,
                                           0, 1, 4,
                                           22, 30, 62,
                                           32, 33, 41,
                                           11, 15, 43,
                                           3, 6, 7,
                                           20, 52, 60,
                                           48, 56, 57], new)
            ori = translate[ori]
            eori = nm.repeat(ori[:, None], n_dof_per_facet, 1)

            ps = ap.interp.poly_spaces['v']
            orders = ps.face_axes_nodes[iep - ps.face_indx[0]]
            eoo = orders % 2
            eoo0, eoo1 = eoo[..., 0], eoo[..., 1]

            i0 = nm.where(eori < 4)
            i1 = nm.where(eori >= 4)

            eori[i0] = nm.bitwise_and(eori[i0], 2*eoo0[i0] + 5)
            eori[i0] = nm.bitwise_and(eori[i0], eoo1[i0] + 6)

            eori[i1] = nm.bitwise_and(eori[i1], eoo0[i1] + 6)
            eori[i1] = nm.bitwise_and(eori[i1], 2*eoo1[i1] + 5)

            ap.ori[iel[:, None], iep] = eori

        n_dof = n_dof_per_facet * facets.shape[0]
        assert_(n_dof == nm.prod(all_dofs.shape))

        return n_dof, all_dofs, remap
Beispiel #28
0
    def set_dofs(self, fun=0.0, region=None, dpn=None, warn=None):
        """
        Set the values of DOFs given by the `region` using a function of space
        coordinates or value `fun`.

        If `fun` is a function, the l2 projection that is global for all region
        facets is used to set the DOFs.

        If `dpn > 1`, and `fun` is a function, it has to return the values
        DOF-by-DOF, i.e. a single one-dimensional vector with all values of the
        first component, then of the second one etc. concatenated
        together.

        Parameters
        ----------
        fun : float or array of length dpn or callable
            The DOF values.
        region : Region
            The region containing the DOFs.
        dpn : int, optional
            The DOF-per-node count. If not given, the number of field
            components is used.
        warn : str, optional
            The warning message printed when the region selects no DOFs.

        Returns
        -------
        nods : array, shape (n_dof,)
            The field DOFs (or node indices) given by the region.
        vals : array, shape (dpn, n_dof)
            The values of the DOFs, DOF-by-DOF when raveled in C (row-major)
            order.
        """
        if region is None:
            region = self.region

        if dpn is None:
            dpn = self.n_components

        nods = []
        vals = []

        aux = self.get_dofs_in_region(region)
        nods = nm.unique(nm.hstack(aux))

        if nm.isscalar(fun):
            vals = nm.repeat([fun], nods.shape[0] * dpn)

        elif isinstance(fun, nm.ndarray):
            assert_(len(fun) == dpn)
            vals = nm.repeat(fun, nods.shape[0])

        elif callable(fun):
            import scipy.sparse as sps
            from sfepy.solvers.ls import solve
            from sfepy.discrete.integrals import Integral
            from sfepy.discrete.fem.utils import prepare_remap
            import sfepy.discrete.iga as iga
            from sfepy.discrete.iga.extmods.igac import eval_mapping_data_in_qp

            nurbs = self.nurbs
            facets = self._get_facets(region.kind_tdim)

            # Region facet connectivity.
            rconn = self.get_econn('surface', region)

            # Local connectivity.
            remap = prepare_remap(nods, nods.max() + 1)
            lconn = [remap[ii] for ii in rconn]

            # Cell and face(cell) ids for each facet.
            fis = region.get_facet_indices()

            # Integral given by max. NURBS surface degree.
            fdegrees = iga.get_surface_degrees(nurbs.degrees)
            order = fdegrees.max()
            integral = Integral('i', order=2 * order)
            vals, weights = integral.get_qp(self.domain.gel.surface_facet_name)

            # Boundary QP - use tensor product structure.
            bvals = iga.create_boundary_qp(vals, region.tdim)

            # Compute facet basis, jacobians and physical BQP.
            n_dof = len(nods)
            rhs = nm.zeros((dpn, n_dof), dtype=nm.float64)
            rows, cols, mvals = [], [], []
            all_qp = []
            all_fbfs = []
            all_dets = []
            for ii, (ie, ifa) in enumerate(fis):
                qp_coors = bvals[ifa]

                bfs, _, dets = eval_mapping_data_in_qp(qp_coors, nurbs.cps,
                                                       nurbs.weights,
                                                       nurbs.degrees, nurbs.cs,
                                                       nurbs.conn,
                                                       nm.array([ie]))
                # Facet basis.
                fbfs = bfs[..., facets[ifa]][0, :, 0, :]

                # Weight Jacobians by quadrature point weights.
                dets = nm.abs(dets) * weights[None, :, None, None]
                dets = dets[0, :, 0, :]

                # Physical BQP.
                fcps = nurbs.cps[nurbs.conn[ie, facets[ifa]]]
                qp = nm.dot(fbfs, fcps)

                all_qp.append(qp)
                all_fbfs.append(fbfs)
                all_dets.append(dets)

            # DOF values in the physical BQP.
            qps = nm.concatenate(all_qp)
            vals = nm.asarray(fun(qps))
            vals.shape = (dpn, qps.shape[0])

            n_qp_face = len(bvals[0])

            # Assemble l2 projection system.
            for ii, (ie, ifa) in enumerate(fis):
                # Assembling indices.
                elc = lconn[ii]

                fvals = vals[:, n_qp_face * ii:n_qp_face * (ii + 1)]

                fbfs = all_fbfs[ii]
                dets = all_dets[ii]

                # Local projection system.
                for idof in range(dpn):
                    lrhs = (fbfs * (fvals[idof, :, None] * dets)).sum(0)
                    rhs[idof, elc] += lrhs

                lmtx = ((fbfs[..., None] * fbfs[:, None, :]) *
                        dets[..., None]).sum(0)

                er, ec = nm.meshgrid(elc, elc)
                rows.append(er.ravel())
                cols.append(ec.ravel())
                mvals.append(lmtx.ravel())

            rows = nm.concatenate(rows)
            cols = nm.concatenate(cols)
            mvals = nm.concatenate(mvals)
            mtx = sps.coo_matrix((mvals, (rows, cols)), shape=(n_dof, n_dof))

            vals = nm.zeros((dpn, n_dof), dtype=nm.float64)

            # Solve l2 projection system.
            for idof in range(dpn):
                dofs = solve(mtx, rhs[idof, :])
                vals[idof, remap[nods]] = dofs

        else:
            raise ValueError('unknown function/value type! (%s)' % type(fun))

        return nods, vals
Beispiel #29
0
    def set_dofs(self, fun=0.0, region=None, dpn=None, warn=None):
        """
        Set the values of DOFs given by the `region` using a function of space
        coordinates or value `fun`.

        If `fun` is a function, the l2 projection that is global for all region
        facets is used to set the DOFs.

        If `dpn > 1`, and `fun` is a function, it has to return the values
        DOF-by-DOF, i.e. a single one-dimensional vector with all values of the
        first component, then of the second one etc. concatenated
        together.

        Parameters
        ----------
        fun : float or array of length dpn or callable
            The DOF values.
        region : Region
            The region containing the DOFs.
        dpn : int, optional
            The DOF-per-node count. If not given, the number of field
            components is used.
        warn : str, optional
            The warning message printed when the region selects no DOFs.

        Returns
        -------
        nods : array, shape (n_dof,)
            The field DOFs (or node indices) given by the region.
        vals : array, shape (dpn, n_dof)
            The values of the DOFs, DOF-by-DOF when raveled in C (row-major)
            order.
        """
        if region is None:
            region = self.region

        if dpn is None:
            dpn = self.n_components

        nods = []
        vals = []

        aux = self.get_dofs_in_region(region)
        nods = nm.unique(nm.hstack(aux))

        if nm.isscalar(fun):
            vals = nm.repeat([fun], nods.shape[0] * dpn)

        elif isinstance(fun, nm.ndarray):
            assert_(len(fun) == dpn)
            vals = nm.repeat(fun, nods.shape[0])

        elif callable(fun):
            import scipy.sparse as sps
            from sfepy.solvers.ls import solve
            from sfepy.discrete.integrals import Integral
            from sfepy.discrete.fem.utils import prepare_remap
            import sfepy.discrete.iga as iga
            from sfepy.discrete.iga.extmods.igac import eval_mapping_data_in_qp

            nurbs = self.nurbs
            facets = self._get_facets(region.kind_tdim)

            # Region facet connectivity.
            rconn = self.get_econn('surface', region)

            # Local connectivity.
            remap = prepare_remap(nods, nods.max() + 1)
            lconn = [remap[ii] for ii in rconn]

            # Cell and face(cell) ids for each facet.
            fis = region.get_facet_indices()

            # Integral given by max. NURBS surface degree.
            fdegrees = iga.get_surface_degrees(nurbs.degrees)
            order = fdegrees.max()
            integral = Integral('i', order=2*order)
            vals, weights = integral.get_qp(self.domain.gel.surface_facet_name)

            # Boundary QP - use tensor product structure.
            bvals = iga.create_boundary_qp(vals, region.tdim)

            # Compute facet basis, jacobians and physical BQP.
            n_dof = len(nods)
            rhs = nm.zeros((dpn, n_dof), dtype=nm.float64)
            rows, cols, mvals = [], [], []
            all_qp = []
            all_fbfs = []
            all_dets = []
            for ii, (ie, ifa) in enumerate(fis):
                qp_coors = bvals[ifa]

                bfs, _, dets = eval_mapping_data_in_qp(qp_coors, nurbs.cps,
                                                       nurbs.weights,
                                                       nurbs.degrees,
                                                       nurbs.cs,
                                                       nurbs.conn,
                                                       nm.array([ie]))
                # Facet basis.
                fbfs = bfs[..., facets[ifa]][0, :, 0, :]

                # Weight Jacobians by quadrature point weights.
                dets = nm.abs(dets) * weights[None, :, None, None]
                dets = dets[0, :, 0, :]

                # Physical BQP.
                fcps = nurbs.cps[nurbs.conn[ie, facets[ifa]]]
                qp = nm.dot(fbfs, fcps)

                all_qp.append(qp)
                all_fbfs.append(fbfs)
                all_dets.append(dets)

            # DOF values in the physical BQP.
            qps = nm.concatenate(all_qp)
            vals = nm.asarray(fun(qps))
            vals.shape = (dpn, qps.shape[0])

            n_qp_face = len(bvals[0])

            # Assemble l2 projection system.
            for ii, (ie, ifa) in enumerate(fis):
                # Assembling indices.
                elc = lconn[ii]

                fvals = vals[:, n_qp_face * ii : n_qp_face * (ii + 1)]

                fbfs = all_fbfs[ii]
                dets = all_dets[ii]

                # Local projection system.
                for idof in xrange(dpn):
                    lrhs = (fbfs * (fvals[idof, :, None] * dets)).sum(0)
                    rhs[idof, elc] += lrhs

                lmtx = ((fbfs[..., None] * fbfs[:, None, :])
                        * dets[..., None]).sum(0)

                er, ec = nm.meshgrid(elc, elc)
                rows.append(er.ravel())
                cols.append(ec.ravel())
                mvals.append(lmtx.ravel())

            rows = nm.concatenate(rows)
            cols = nm.concatenate(cols)
            mvals = nm.concatenate(mvals)
            mtx = sps.coo_matrix((mvals, (rows, cols)), shape=(n_dof, n_dof))

            vals = nm.zeros((dpn, n_dof), dtype=nm.float64)

            # Solve l2 projection system.
            for idof in xrange(dpn):
                dofs = solve(mtx, rhs[idof, :])
                vals[idof, remap[nods]] = dofs

        else:
            raise ValueError('unknown function/value type! (%s)' % type(fun))

        return nods, vals
Beispiel #30
0
    def _setup_facet_dofs(self, dim, facet_desc, offset):
        """
        Helper function to setup facet DOF connectivity, works for both
        edges and faces.
        """
        facet_desc = nm.array(facet_desc)
        n_dof_per_facet = facet_desc.shape[1]

        cmesh = self.domain.cmesh

        facets = self.region.entities[dim]
        ii = nm.arange(facets.shape[0], dtype=nm.int32)
        all_dofs = offset + expand_nodes_to_dofs(ii, n_dof_per_facet)

        # Prepare global facet id remapping to field-local numbering.
        remap = prepare_remap(facets, cmesh.num[dim])

        cconn = self.region.domain.cmesh.get_conn(self.region.tdim, dim)
        offs = cconn.offsets

        n_f = self.gel.edges.shape[0] if dim == 1 else self.gel.faces.shape[0]
        n_fp = 2 if dim == 1 else self.gel.surface_facet.n_vertex

        oris = cmesh.get_orientations(dim)
        ap = self.ap

        gcells = self.region.get_cells()
        n_el = gcells.shape[0]

        # Elements of facets.
        iel = nm.arange(n_el, dtype=nm.int32).repeat(n_f)
        ies = nm.tile(nm.arange(n_f, dtype=nm.int32), n_el)

        aux = offs[gcells][:, None] + ies.reshape((n_el, n_f))

        indices = cconn.indices[aux]
        facets_of_cells = remap[indices].ravel()

        # Define global facet dof numbers.
        gdofs = offset + expand_nodes_to_dofs(facets_of_cells, n_dof_per_facet)

        # DOF columns in econn for each facet (repeating same values for
        # each element.
        iep = facet_desc[ies]

        ap.econn[iel[:, None], iep] = gdofs

        ori = oris[aux].ravel()

        if (n_fp == 2) and (ap.interp.gel.name in ['2_4', '3_8']):
            tp_edges = ap.interp.gel.edges
            ecs = ap.interp.gel.coors[tp_edges]
            # True = positive, False = negative edge orientation w.r.t.
            # reference tensor product axes.
            tp_edge_ori = (nm.diff(ecs, axis=1).sum(axis=2) > 0).squeeze()
            aux = nm.tile(tp_edge_ori, n_el)
            ori = nm.where(aux, ori, 1 - ori)

        if n_fp == 2:  # Edges.
            # ori == 1 means the basis has to be multiplied by -1.
            ps = ap.interp.poly_spaces['v']
            orders = ps.node_orders
            eori = nm.repeat(ori[:, None], n_dof_per_facet, 1)
            eoo = orders[iep] % 2  # Odd orders.
            ap.ori[iel[:, None], iep] = eori * eoo

        elif n_fp == 3:  # Triangular faces.
            raise NotImplementedError

        else:  # Quadrilateral faces.
            # ori encoding in 3 bits:
            # 0: axis swap, 1: axis 1 sign, 2: axis 2 sign
            # 0 = + or False, 1 = - or True
            # 63 -> 000 = 0
            #  0 -> 001 = 1
            # 30 -> 010 = 2
            # 33 -> 011 = 3
            # 11 -> 100 = 4
            #  7 -> 101 = 5
            # 52 -> 110 = 6
            # 56 -> 111 = 7
            # Special cases:
            # Both orders same and even -> 000
            # Both orders same and odd -> 0??
            # Bits 1, 2 are multiplied by (swapped) axial order % 2.
            new = nm.repeat(nm.arange(8, dtype=nm.int32), 3)
            translate = prepare_translate([
                31, 59, 63, 0, 1, 4, 22, 30, 62, 32, 33, 41, 11, 15, 43, 3, 6,
                7, 20, 52, 60, 48, 56, 57
            ], new)
            ori = translate[ori]
            eori = nm.repeat(ori[:, None], n_dof_per_facet, 1)

            ps = ap.interp.poly_spaces['v']
            orders = ps.face_axes_nodes[iep - ps.face_indx[0]]
            eoo = orders % 2
            eoo0, eoo1 = eoo[..., 0], eoo[..., 1]

            i0 = nm.where(eori < 4)
            i1 = nm.where(eori >= 4)

            eori[i0] = nm.bitwise_and(eori[i0], 2 * eoo0[i0] + 5)
            eori[i0] = nm.bitwise_and(eori[i0], eoo1[i0] + 6)

            eori[i1] = nm.bitwise_and(eori[i1], eoo0[i1] + 6)
            eori[i1] = nm.bitwise_and(eori[i1], 2 * eoo1[i1] + 5)

            ap.ori[iel[:, None], iep] = eori

        n_dof = n_dof_per_facet * facets.shape[0]
        assert_(n_dof == nm.prod(all_dofs.shape))

        return n_dof, all_dofs, remap