def get_vectors(self, nodes, region, field, filename=None): normals = compute_nodal_normals(nodes, region, field) if filename is not None: _save_vectors(filename, normals, region, field.domain.mesh, 'n') return normals
def __init__(self, name, nodes, region, field, dof_names, filename=None): Struct.__init__(self, name=name, nodes=nodes, dof_names=dof_names) dim = field.shape[0] assert_(len(dof_names) == dim) normals = compute_nodal_normals(nodes, region, field) if filename is not None: _save_normals(filename, normals, region, field.domain.mesh) ii = nm.abs(normals).argmax(1) n_nod, dim = normals.shape irs = set(range(dim)) data = [] rows = [] cols = [] for idim in xrange(dim): ic = nm.where(ii == idim)[0] if len(ic) == 0: continue ## print ic ## print idim ir = list(irs.difference([idim])) nn = nm.empty((len(ic), dim - 1), dtype=nm.float64) for ik, il in enumerate(ir): nn[:, ik] = -normals[ic, il] / normals[ic, idim] irn = dim * ic + idim ics = [(dim - 1) * ic + ik for ik in xrange(dim - 1)] for ik in xrange(dim - 1): rows.append(irn) cols.append(ics[ik]) data.append(nn[:, ik]) ones = nm.ones((nn.shape[0], ), dtype=nm.float64) for ik, il in enumerate(ir): rows.append(dim * ic + il) cols.append(ics[ik]) data.append(ones) ## print rows ## print cols ## print data rows = nm.concatenate(rows) cols = nm.concatenate(cols) data = nm.concatenate(data) n_np_dof = n_nod * (dim - 1) mtx = sp.coo_matrix((data, (rows, cols)), shape=(n_nod * dim, n_np_dof)) self.n_dof = n_np_dof self.mtx = mtx.tocsr()
def __init__(self, name, nodes, region, field, dof_names, filename=None): Struct.__init__(self, name=name, nodes=nodes, dof_names=dof_names) dim = field.shape[0] assert_(len(dof_names) == dim) normals = compute_nodal_normals(nodes, region, field) if filename is not None: _save_normals(filename, normals, region, field.domain.mesh) ii = nm.abs(normals).argmax(1) n_nod, dim = normals.shape irs = set(range(dim)) data = [] rows = [] cols = [] for idim in xrange(dim): ic = nm.where(ii == idim)[0] if len(ic) == 0: continue ## print ic ## print idim ir = list(irs.difference([idim])) nn = nm.empty((len(ic), dim - 1), dtype=nm.float64) for ik, il in enumerate(ir): nn[:,ik] = - normals[ic,il] / normals[ic,idim] irn = dim * ic + idim ics = [(dim - 1) * ic + ik for ik in xrange(dim - 1)] for ik in xrange(dim - 1): rows.append(irn) cols.append(ics[ik]) data.append(nn[:,ik]) ones = nm.ones( (nn.shape[0],), dtype = nm.float64 ) for ik, il in enumerate(ir): rows.append(dim * ic + il) cols.append(ics[ik]) data.append(ones) ## print rows ## print cols ## print data rows = nm.concatenate(rows) cols = nm.concatenate(cols) data = nm.concatenate(data) n_np_dof = n_nod * (dim - 1) mtx = sp.coo_matrix((data, (rows, cols)), shape=(n_nod * dim, n_np_dof)) self.n_dof = n_np_dof self.mtx = mtx.tocsr()
def __init__(self, name, nodes, region, field, dof_names, filename=None): Struct.__init__(self, name=name, nodes=nodes, dof_names=dof_names) dim = field.shape[0] assert_(len(dof_names) == dim) normals = compute_nodal_normals(nodes, region, field) if filename is not None: _save_normals(filename, normals, region, field.domain.mesh) n_nod, dim = normals.shape data = normals.ravel() rows = nm.arange(data.shape[0]) cols = nm.repeat(nm.arange(n_nod), dim) mtx = sp.coo_matrix((data, (rows, cols)), shape=(n_nod * dim, n_nod)) self.n_dof = n_nod self.mtx = mtx.tocsr()
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