def facet_info_and_dofmap(V): """ Return three lists 1) A list which maps facet index to dof 2) A list which maps facet index to facet area 2) A list which maps facet index to facet midpoint """ mesh = V.mesh() dofmap = V.dofmap() ndim = V.ufl_cell().topological_dimension() # Loop through cells and get dofs for each cell facet_dofs = [None] * mesh.num_facets() facet_area = [None] * mesh.num_facets() facet_midp = [None] * mesh.num_facets() for cell in dolfin.cells(mesh): dofs = dofmap.cell_dofs(cell.index()) facet_idxs = cell.entities(ndim - 1) # Only works for functions with one dof on each facet assert len(dofs) == len(facet_idxs) # Loop through connected facets and store dofs for each facet for i, fidx in enumerate(facet_idxs): facet_dofs[fidx] = dofs[i] facet_area[fidx] = cell.facet_area(i) mp = dolfin.Facet(mesh, fidx).midpoint() facet_midp[fidx] = (mp.x(), mp.y()) return facet_dofs, facet_area, facet_midp
def get_normal(self, mesh): facet_iter = df.SubsetIterator(self.boundaries, self.id) normal = np.empty((self.num_facets, self.g_dim)) for i, facet in enumerate(facet_iter): fs = df.Facet(mesh, facet.index()) normal[i, :] = -1 * \ np.array([fs.normal()[j] for j in range(self.g_dim)]) return normal
def _transferFacetMeshFun(fun, subfun, zero): # get meshes mesh = fun.mesh() submesh = subfun.mesh() # cell mapping parent_cell_indices = submesh.data().array("parent_cell_indices", 3).astype(np.int) parent_vert_indices = submesh.data().array("parent_vertex_indices", 0).astype(np.int) # space dimension dim = fun.mesh().geometry().dim() # initialize facets submesh.init(dim - 1, dim) # loop over cell on parent mesh for parent_cell in dlfn.cells(mesh): parent_cell_id = parent_cell.index() # loop over facet of parent cell for parent_facet_id in parent_cell.entities(dim - 1).astype(np.int): if fun[parent_facet_id] != zero: # get parent vertices parent_facet = dlfn.Facet(mesh, parent_facet_id) parent_facet_vert_ids = parent_facet.entities(0) # find matching cell in sub mesh (invert mapping) cell_id = np.where(parent_cell_indices == parent_cell_id)[0] if cell_id.size > 0: assert cell_id.size == 1 cell = dlfn.Cell(submesh, cell_id[0]) # loop over child facet for facet_id in cell.entities(dim - 1): facet = dlfn.Facet(submesh, facet_id) facet_match = True for vert_id in facet.entities(0): if parent_vert_indices[ vert_id] not in parent_facet_vert_ids: facet_match = False break if facet_match == True: subfun.set_value(facet_id, fun[parent_facet_id]) break
def surface_normal(tag, facet_f, point): '''Normal of taged surface which points away from the point''' # NOTE: as this is a constant it will only work for a flat surface mesh = facet_f.mesh() tdim = facet_f.dim() assert tdim == mesh.topology().dim() - 1 assert mesh.geometry().dim() == 3 point = df.Point(*point) facets, = np.where(facet_f.array() == tag) facets = iter(facets) first = df.Facet(mesh, next(facets)) n = first.normal() # Is this a flat surface assert all( abs(abs(df.Facet(mesh, f).normal().dot(n)) - 1) < 1E-10 for f in facets) mid = first.midpoint() return n.array() if n.dot(mid - point) > 0 else -1 * n.array()
def boring(mesh_2d, inner_size): ''' A mesh2d is assumed to be be a cube [-inner_size, inner_size]^2. The curve is mostly a collection of boundary edges. ''' facet_f = df.MeshFunction('size_t', mesh_2d, 1, 0) mesh_2d.init(2, 1) # Mesh for the curve is tricky as we need to find the line in the faces def union(domains, A=inner_size, tol=1E-10): def body(domains): if isinstance(domains, str): if domains: return '( %s )' % domains else: return '' else: return ' || '.join(map(body, domains)) return df.CompiledSubDomain(body(domains), A=A, tol=tol) lines = { 4: union('near(x[1], A, tol) && near(x[2], A, tol)'), 3: union('near(x[2], -x[0], tol)'), 2: union('near(x[2], x[1], tol)'), 1: union([ 'near(x[0], -A, tol) && near(x[2], -A, tol)', 'near(x[1], A, tol) && near(x[0], -A, tol)', 'near(x[1], -A, tol) && near(x[0], -A, tol)' ]) } for tag, line in lines.items(): # Get candidates facets = set( sum((cell.entities(1).tolist() for cell in df.SubsetIterator(mesh_2d.marking_function, tag)), [])) for facet in facets: if line.inside(df.Facet(mesh_2d, facet).midpoint().array(), True): facet_f[int(facet)] = 1 return facet_f
def get_basis(self, mesh, vertices): facet_iter = df.SubsetIterator(self.boundaries, self.id) basis = np.empty((self.num_facets * self.g_dim, self.g_dim)) for i, facet in enumerate(facet_iter): fs = df.Facet(mesh, facet.index()) basis[i * self.g_dim, :] = vertices[i*self.g_dim, :] -\ vertices[i*self.g_dim+1, :] basis[i * self.g_dim, :] /= np.linalg.norm(basis[i * self.g_dim, :]) basis[self.g_dim*(i+1)-1, :] = -1 * \ np.array([fs.normal()[j] for j in range(self.g_dim)]) if (self.g_dim == 3): basis[i*self.g_dim + 1, :] = \ np.cross(basis[self.g_dim*(i+1)-1, :], basis[i*self.g_dim, :]) return basis
emesh = df.BoundaryMesh(mesh, 'exterior') time = df.Timer('map') time.start() mapping = build_embedding_map(emesh, mesh, tol=1E-14) dt = time.stop() mesh_x = mesh.coordinates() emesh_x = emesh.coordinates() assert max( np.linalg.norm(ex - mesh_x[to]) for ex, to in zip(emesh_x, mapping[0])) < 1E-14 assert max( df.Facet(mesh, entity).midpoint().distance( df.Cell(emesh, cell).midpoint()) for cell, entity in enumerate(mapping[1])) < 1E-14 if n0 is not None: rate = np.log(dt / dt0) / np.log(float(n) / n0) else: rate = np.nan print n, dt, rate n0, dt0 = n, dt # Check creation mesh = df.UnitCubeMesh(10, 10, 10) f = df.MeshFunction('size_t', mesh, mesh.topology().dim() - 1, 0) chi = df.CompiledSubDomain('near(x[i], 0.5)', i=0) for i in range(3):
def pbc_facet_function(part_vectors, mesh, facet_function, per_choice: dict, dim=2, tol=GEO_TOLERANCE): """[summary] Parameters ---------- part_vectors : np.array mesh : Mesh facet_function : MeshFunction per_choice : dict key can be : 'X', 'Y' values : tuple (value of facetfunction for master, value for slave) Ex : {'X' : (3,5)} tol : float, optional Returns ------- PeriodicDomain """ # ! Not tested yet basis = list() for i in range(np.size(part_vectors, 1)): basis.append(fe.as_vector(part_vectors[:, i])) per_values = [val for couple in per_choice for val in couple] coordinates = dict() mesh.init(1, 0) # Compute connectivity between given pair of dimensions. for val in per_values: points_for_val = list() facet_idces = facet_function.where_equal(val) for i in facet_idces: vertices_idces = fe.Facet(mesh, i).entities(0) for j in vertices_idces: coord = fe.Vertex(mesh, j).point().array() points_for_val.append(coord) coordinates[val] = points_for_val master_tests, slave_tests, per_vectors = list(), list(), list() for key, (master_idx, slave_idx) in per_choice.items(): def master_test(x): return any( np.allclose(x, pt, atol=tol) for pt in coordinates[master_idx]) def slave_test(x): return any( np.allclose(x, pt, atol=tol) for pt in coordinates[slave_idx]) master_tests.append(master_test) slave_tests.append(slave_test) if key.lower() == "x": per_vectors.append(basis[0]) elif key.lower() == "y": per_vectors.append(basis[1]) return PeriodicDomain(per_vectors, master_tests, slave_tests, dim, tol)