Ejemplo n.º 1
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()
Ejemplo n.º 2
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
Ejemplo n.º 3
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
Ejemplo n.º 4
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()
Ejemplo n.º 5
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
Ejemplo n.º 6
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)
        for ig, ap in self.aps.iteritems():
            gcells = self.region.get_cells(ig, offset=False)
            n_el = gcells.shape[0]

            indices = cconn.indices[offs[gcells[0]]:offs[gcells[-1]+1]]
            facets_of_cells = remap[indices]

            ori = oris[offs[gcells[0]]:offs[gcells[-1]+1]]
            perms = facet_perms[ig][ori]

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

            # 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)

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

            iaux = nm.arange(gdofs.shape[0], dtype=nm.int32)
            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
Ejemplo n.º 7
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)
        for ig, ap in self.aps.iteritems():
            gcells = self.region.get_cells(ig, offset=False)
            n_el = gcells.shape[0]

            indices = cconn.indices[offs[gcells[0]]:offs[gcells[-1] + 1]]
            facets_of_cells = remap[indices]

            ori = oris[offs[gcells[0]]:offs[gcells[-1] + 1]]
            perms = facet_perms[ig][ori]

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

            # 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)

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

            iaux = nm.arange(gdofs.shape[0], dtype=nm.int32)
            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
Ejemplo n.º 8
0
    def _setup_facet_dofs(self, facets, facet_desc, facet_perms,
                          get_facets, 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]

        # Prepare global facet id remapping to field-local numbering.
        uids = []
        for ig, ap in self.aps.iteritems():
            ii = get_facets(ig)
            uid_i = facets.uid_i[ii]

            uids.append(uid_i)

        uids = nm.unique(nm.concatenate(uids))
        n_uid = uids.shape[0]
        lids = nm.arange(n_uid, dtype=nm.int32)
        remap = prepare_remap(uids, facets.n_unique)

        all_dofs = offset + expand_nodes_to_dofs(lids, n_dof_per_facet)

        for ig, ap in self.aps.iteritems():
            ori = facets.oris[ig]
            perms = facet_perms[ig][ori]

            ii = get_facets(ig)
            g_uid = facets.uid_i[ii]
            uid = remap[g_uid]

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

            # Elements of facets.
            iel = facets.indices[ii, 1]

            ies = facets.indices[ii, 2]
            # DOF columns in econn for each facet.
            iep = facet_desc[ies]

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

        n_dof = n_dof_per_facet * n_uid
        assert_(n_dof == nm.prod(all_dofs.shape))

        return n_dof, all_dofs, remap
Ejemplo n.º 9
0
    def __init__(self, name, region, efaces, volume_econn, ig):
        """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(ig)

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

        try:
            ee = volume_econn[face_indices[:,0]]

        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)
        remap = prepare_remap(nodes, nodes.max() + 1)
        leconn = remap[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.ig = ig
        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
Ejemplo n.º 10
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.all_vertices, region.n_v_max)
        n_dof = region.all_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
Ejemplo n.º 11
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()
Ejemplo n.º 12
0
    def _setup_facet_dofs(self, facets, facet_desc, get_facets, 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]

        # Prepare global facet id remapping to field-local numbering.
        uids = []
        for ig, ap in self.aps.iteritems():
            ii = get_facets(ig)
            uid_i = facets.uid_i[ii]

            uids.append(uid_i)

        uids = nm.unique(nm.concatenate(uids))
        n_uid = uids.shape[0]
        lids = nm.arange(n_uid, dtype=nm.int32)
        remap = prepare_remap(uids, facets.n_unique)

        all_dofs = offset + expand_nodes_to_dofs(lids, n_dof_per_facet)
        for ig, ap in self.aps.iteritems():
            n_fp = facets.n_fps[ig]
            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()

            else:
                tp_edge_ori = None

            ori = facets.get_orientation(ig, tp_edge_ori)

            ii = get_facets(ig)
            g_uid = facets.uid_i[ii]
            uid = remap[g_uid]

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

            # Elements of facets.
            iel = facets.indices[ii, 1]

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

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

            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 * n_uid
        assert_(n_dof == nm.prod(all_dofs.shape))

        return n_dof, all_dofs, remap
Ejemplo n.º 13
0
    def _setup_facet_dofs(self, dim, facet_desc, get_facets, 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)
        for ig, ap in self.aps.iteritems():
            gcells = self.region.get_cells(ig, offset=False)
            n_el = gcells.shape[0]

            indices = cconn.indices[offs[gcells[0]] : offs[gcells[-1] + 1]]
            facets_of_cells = remap[indices]

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

            # 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)

            # 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[offs[gcells[0]] : offs[gcells[-1] + 1]]

            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