def get_coors(self, ig=None): """ Get the coordinates of vertices of unique facets in group `ig`. Parameters ---------- ig : int, optional The element group. If None, the coordinates for all groups are returned, filled with zeros at places of missing vertices, i.e. where facets having less then the full number of vertices (`n_v`) are. Returns ------- coors : array The coordinates in an array of shape `(n_f, n_v, dim)`. uid : array The unique ids of facets in the order of `coors`. """ cc = self.domain.get_mesh_coors() if ig is None: uid, ii = unique(self.uid_i, return_index=True) facets = self.facets[ii] aux = insert_strided_axis(facets, 2, cc.shape[1]) coors = nm.where(aux >= 0, cc[facets], 0.0) else: uid_i = self.uid_i[self.indx[ig]] uid, ii = unique(uid_i, return_index=True) coors = cc[self.facets[ii, :self.n_fps[ig]]] return coors, uid
def get_coors(self, ig=None): """ Get the coordinates of vertices of unique facets in group `ig`. Parameters ---------- ig : int, optional The element group. If None, the coordinates for all groups are returned, filled with zeros at places of missing vertices, i.e. where facets having less then the full number of vertices (`n_v`) are. Returns ------- coors : array The coordinates in an array of shape `(n_f, n_v, dim)`. uid : array The unique ids of facets in the order of `coors`. """ cc = self.domain.get_mesh_coors() if ig is None: uid, ii = unique(self.uid_i, return_index=True) facets = self.facets[ii] aux = insert_strided_axis(facets, 2, cc.shape[1]) coors = nm.where(aux >= 0, cc[facets], 0.0) else: uid_i = self.uid_i[self.indx[ig]] uid, ii = unique(uid_i, return_index=True) coors = cc[self.facets[ii,:self.n_fps[ig]]] return coors, uid
def treat_pbcs(self, master_equations): """ Treat dofs with periodic BC. """ umeq, indx = unique(master_equations, return_index=True) indx.sort() self.mtx = self.mtx[indx]
def get_coors(self, ig=0): """ Get the coordinates of vertices of unique facets in group `ig`. Returns ------- coors : array The coordinates in an array of shape `(n_f, n_v, dim)`. uid : array The unique ids of facets in the order of `coors`. """ cc = self.domain.get_mesh_coors() uid_i = self.uid_i[self.indx[ig]] uid, ii = unique(uid_i, return_index=True) coors = cc[self.facets[ii,:self.n_fps[ig]]] return coors, uid
def describe_dual_surface(self, surface): n_fa, n_edge = surface.n_fa, self.sgel.n_edge mesh_coors = self.mesh_coors # Face centres. fcoors = mesh_coors[surface.econn] centre_coors = nm.dot(self.bf.squeeze(), fcoors) surface_coors = mesh_coors[surface.nodes] dual_coors = nm.r_[surface_coors, centre_coors] coor_offset = surface.nodes.shape[0] # Normals in primary mesh nodes. nodal_normals = compute_nodal_normals(surface.nodes, self.region, self.field) ee = surface.leconn[:, self.sgel.edges].copy() edges_per_face = ee.copy() sh = edges_per_face.shape ee.shape = edges_per_face.shape = (sh[0] * sh[1], sh[2]) edges_per_face.sort(axis=1) eo = nm.empty((sh[0] * sh[1], ), dtype=nm.object) eo[:] = [tuple(ii) for ii in edges_per_face] ueo, e_sort, e_id = unique(eo, return_index=True, return_inverse=True) ueo = edges_per_face[e_sort] # edge centre, edge point 1, face centre, edge point 2 conn = nm.empty((n_edge * n_fa, 4), dtype=nm.int32) conn[:, 0] = e_id conn[:, 1] = ee[:, 0] conn[:,2] = nm.repeat(nm.arange(n_fa, dtype=nm.int32), n_edge) \ + coor_offset conn[:, 3] = ee[:, 1] # face centre, edge point 2, edge point 1 tri_conn = nm.ascontiguousarray(conn[:, [2, 1, 3]]) # Ensure orientation - outward normal. cc = dual_coors[tri_conn] v1 = cc[:, 1] - cc[:, 0] v2 = cc[:, 2] - cc[:, 0] normals = nm.cross(v1, v2) nn = nodal_normals[surface.leconn].sum(axis=1).repeat(n_edge, 0) centre_normals = (1.0 / surface.n_fp) * nn centre_normals /= la.norm_l2_along_axis(centre_normals)[:, None] dot = nm.sum(normals * centre_normals, axis=1) assert_((dot > 0.0).all()) # Prepare mapping from reference triangle e_R to a # triangle within reference face e_D. gel = self.gel.surface_facet ref_coors = gel.coors ref_centre = nm.dot(self.bf.squeeze(), ref_coors) cc = nm.r_[ref_coors, ref_centre[None, :]] rconn = nm.empty((n_edge, 3), dtype=nm.int32) rconn[:, 0] = gel.n_vertex rconn[:, 1] = gel.edges[:, 0] rconn[:, 2] = gel.edges[:, 1] map_er_ed = VolumeMapping(cc, rconn, gel=gel) # Prepare mapping from reference triangle e_R to a # physical triangle e. map_er_e = SurfaceMapping(dual_coors, tri_conn, gel=gel) # Compute triangle basis (edge) vectors. nn = surface.nodes[ueo] edge_coors = mesh_coors[nn] edge_centre_coors = 0.5 * edge_coors.sum(axis=1) edge_normals = 0.5 * nodal_normals[ueo].sum(axis=1) edge_normals /= la.norm_l2_along_axis(edge_normals)[:, None] nn = surface.nodes[ueo] edge_dirs = edge_coors[:, 1] - edge_coors[:, 0] edge_dirs /= la.norm_l2_along_axis(edge_dirs)[:, None] edge_ortho = nm.cross(edge_normals, edge_dirs) edge_ortho /= la.norm_l2_along_axis(edge_ortho)[:, None] # Primary face - dual sub-faces map. # i-th row: indices to conn corresponding to sub-faces of i-th face. face_map = nm.arange(n_fa * n_edge, dtype=nm.int32) face_map.shape = (n_fa, n_edge) # The actual connectivity for assembling (unique nodes per master # faces). asm_conn = e_id[face_map] n_nod = ueo.shape[0] # One node per unique edge. n_components = self.dim - 1 dual_surface = Struct(name='dual_surface_description', dim=self.dim, n_dual_fa=conn.shape[0], n_dual_fp=self.dim, n_fa=n_fa, n_edge=n_edge, n_nod=n_nod, n_components=n_components, n_dof=n_nod * n_components, dual_coors=dual_coors, coor_offset=coor_offset, e_sort=e_sort, conn=conn, tri_conn=tri_conn, map_er_e=map_er_e, map_er_ed=map_er_ed, face_map=face_map, asm_conn=asm_conn, nodal_normals=nodal_normals, edge_centre_coors=edge_centre_coors, edge_normals=edge_normals, edge_dirs=edge_dirs, edge_ortho=edge_ortho) return dual_surface
def describe_dual_surface(self, surface): n_fa, n_edge = surface.n_fa, self.sgel.n_edge mesh_coors = self.mesh_coors # Face centres. fcoors = mesh_coors[surface.econn] centre_coors = nm.dot(self.bf.squeeze(), fcoors) surface_coors = mesh_coors[surface.nodes] dual_coors = nm.r_[surface_coors, centre_coors] coor_offset = surface.nodes.shape[0] # Normals in primary mesh nodes. nodal_normals = compute_nodal_normals(surface.nodes, self.region, self.field) ee = surface.leconn[:,self.sgel.edges].copy() edges_per_face = ee.copy() sh = edges_per_face.shape ee.shape = edges_per_face.shape = (sh[0] * sh[1], sh[2]) edges_per_face.sort(axis=1) eo = nm.empty((sh[0] * sh[1],), dtype=nm.object) eo[:] = [tuple(ii) for ii in edges_per_face] ueo, e_sort, e_id = unique(eo, return_index=True, return_inverse=True) ueo = edges_per_face[e_sort] # edge centre, edge point 1, face centre, edge point 2 conn = nm.empty((n_edge * n_fa, 4), dtype=nm.int32) conn[:,0] = e_id conn[:,1] = ee[:,0] conn[:,2] = nm.repeat(nm.arange(n_fa, dtype=nm.int32), n_edge) \ + coor_offset conn[:,3] = ee[:,1] # face centre, edge point 2, edge point 1 tri_conn = nm.ascontiguousarray(conn[:,[2,1,3]]) # Ensure orientation - outward normal. cc = dual_coors[tri_conn] v1 = cc[:,1] - cc[:,0] v2 = cc[:,2] - cc[:,0] normals = nm.cross(v1, v2) nn = nodal_normals[surface.leconn].sum(axis=1).repeat(n_edge, 0) centre_normals = (1.0 / surface.n_fp) * nn centre_normals /= la.norm_l2_along_axis(centre_normals)[:,None] dot = nm.sum(normals * centre_normals, axis=1) assert_((dot > 0.0).all()) # Prepare mapping from reference triangle e_R to a # triangle within reference face e_D. gel = self.gel.surface_facet ref_coors = gel.coors ref_centre = nm.dot(self.bf.squeeze(), ref_coors) cc = nm.r_[ref_coors, ref_centre[None,:]] rconn = nm.empty((n_edge, 3), dtype=nm.int32) rconn[:,0] = gel.n_vertex rconn[:,1] = gel.edges[:,0] rconn[:,2] = gel.edges[:,1] map_er_ed = VolumeMapping(cc, rconn, gel=gel) # Prepare mapping from reference triangle e_R to a # physical triangle e. map_er_e = SurfaceMapping(dual_coors, tri_conn, gel=gel) # Compute triangle basis (edge) vectors. nn = surface.nodes[ueo] edge_coors = mesh_coors[nn] edge_centre_coors = 0.5 * edge_coors.sum(axis=1) edge_normals = 0.5 * nodal_normals[ueo].sum(axis=1) edge_normals /= la.norm_l2_along_axis(edge_normals)[:,None] nn = surface.nodes[ueo] edge_dirs = edge_coors[:,1] - edge_coors[:,0] edge_dirs /= la.norm_l2_along_axis(edge_dirs)[:,None] edge_ortho = nm.cross(edge_normals, edge_dirs) edge_ortho /= la.norm_l2_along_axis(edge_ortho)[:,None] # Primary face - dual sub-faces map. # i-th row: indices to conn corresponding to sub-faces of i-th face. face_map = nm.arange(n_fa * n_edge, dtype=nm.int32) face_map.shape = (n_fa, n_edge) # The actual connectivity for assembling (unique nodes per master # faces). asm_conn = e_id[face_map] n_nod = ueo.shape[0] # One node per unique edge. n_components = self.dim - 1 dual_surface = Struct(name = 'dual_surface_description', dim = self.dim, n_dual_fa = conn.shape[0], n_dual_fp = self.dim, n_fa = n_fa, n_edge = n_edge, n_nod = n_nod, n_components = n_components, n_dof = n_nod * n_components, dual_coors = dual_coors, coor_offset = coor_offset, e_sort = e_sort, conn = conn, tri_conn = tri_conn, map_er_e = map_er_e, map_er_ed = map_er_ed, face_map = face_map, asm_conn = asm_conn, nodal_normals = nodal_normals, edge_centre_coors = edge_centre_coors, edge_normals = edge_normals, edge_dirs = edge_dirs, edge_ortho = edge_ortho) return dual_surface