def mesh_diameter(mesh): # FIXME: Quadratic algorithm is too slow! """Return mesh diameter, i.e. \sup_{x,y \in mesh} |x-y|. Algorithm loops quadratically over boundary facets.""" not_working_in_parallel("Function 'mesh_diameter'") assert mesh.topology().dim() == mesh.geometry().dim(), \ "Function 'mesh_diameter' not working on manifolds." tdim = mesh.topology().dim() mesh.init(tdim-1, tdim) diameter = 0.0 for f0 in facets(mesh): if not f0.exterior(): continue for f1 in facets(mesh): if not f1.exterior(): continue for v0 in vertices(f0): for v1 in vertices(f1): diameter = max(diameter, v0.point().distance(v1.point())) return diameter
def mesh_fixup(mesh): """Refine cells which have all vertices on boundary and return a new mesh.""" cf = CellFunction('bool', mesh) tdim = mesh.topology().dim() mesh.init(tdim-1, tdim) for f in facets(mesh): # Boundary facet? # TODO: Here we could check supplied facet function or subdomain if not f.exterior(): continue # Pick adjacent cell c = Cell(mesh, f.entities(tdim)[0]) # Number of vertices on boundary num_bad_vertices = sum(1 for v in vertices(c) if any(fv.exterior() for fv in facets(v))) assert num_bad_vertices <= c.num_vertices() # Refine cell if all vertices are on boundary if num_bad_vertices == c.num_vertices(): cf[c] = True return refine(mesh, cf)
def get_long_field(mesh, mesh_type="biv"): fiber_params = setup_fiber_parameters() fiber_params["fiber_angle_endo"] = -90 fiber_params["fiber_angle_epi"] = -90 if mesh_type == "biv": # We need to set the markers for then LV and RV facets ffun = dolfin.MeshFunction("size_t", mesh, 2, mesh.domains()) markers = get_fiber_markers("biv") # Mark the mesh with same markers on the LV and RV before # running the LDRB algorithm markers["ENDO_RV"] = markers["ENDO_LV"] for facet in dolfin.facets(mesh): if ffun[facet] != 0: mesh.domains().set_marker( (facet.index(), markers[ffun[facet]]), 2) f0 = generate_fibers(mesh, fiber_params)[0] f0.rename("longitudinal", "local_basis_function") if mesh_type == "biv": # Put the correct markers markers = get_fiber_markers("biv") for facet in dolfin.facets(mesh): if ffun[facet] != 0: mesh.domains().set_marker( (facet.index(), markers[ffun[facet]]), 2) return f0
def create_measures(self): for rom_cell_counter, rom_cell in enumerate(df.cells( self._mesh_coarse)): form = FluxForm(df.Function(self._V), df.Function(self._Vc)) facetfct = df.MeshFunction('size_t', self._mesh_fine, self._mesh_fine.topology().dim() - 1) facetfct.set_all(0) for local_facet_id, rom_facet in enumerate(df.facets(rom_cell)): for fom_facet in df.facets(self._mesh_fine): mp = fom_facet.midpoint() p0 = df.Vertex(self._mesh_coarse, rom_facet.entities(0)[0]) p1 = df.Vertex(self._mesh_coarse, rom_facet.entities(0)[1]) p0 = df.Point(np.array([p0.x(0), p0.x(1)])) p1 = df.Point(np.array([p1.x(0), p1.x(1)])) eps = mp.distance(p0) + mp.distance(p1) - p0.distance(p1) if eps < 1e-12: facetfct.set_value(fom_facet.index(), local_facet_id + 1) if self._rom_exterior_facets[rom_facet.index()]: form.append_ds( df.Measure('ds', domain=self._mesh_fine, subdomain_data=facetfct, subdomain_id=local_facet_id + 1)) else: form.append_dS( df.Measure('dS', domain=self._mesh_fine, subdomain_data=facetfct, subdomain_id=local_facet_id + 1)) cellfct = df.MeshFunction('size_t', self._mesh_fine, self._mesh_fine.topology().dim()) cellfct.set_all(0) for fom_cell in df.cells(self._mesh_fine): if rom_cell.contains(fom_cell.midpoint()): cellfct.set_value(fom_cell.index(), 1) form.append_dx( df.Measure('dx', domain=self._mesh_fine, subdomain_data=cellfct, subdomain_id=1)) self._flux_forms.append(form) self._initialized = True
def mesh2d(inner, outer, *meshres, stefan=True): origin = dolfin.Point(0., 0.) if stefan: geometry = mshr.Circle(origin, outer, 2 * meshres[0]) - mshr.Circle( origin, inner, int(0.5 * meshres[0])) mesh = mshr.generate_mesh(geometry, meshres[0]) mesh.init() # Construct of the facet markers: boundary = (dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0), {}) for f in dolfin.facets(mesh): if f.midpoint().distance(origin) <= inner and f.exterior(): boundary[0][f] = 1 # inner radius boundary[1]['inner'] = 1 elif f.midpoint().distance(origin) >= (inner + outer) / 2 and f.exterior(): boundary[0][f] = 2 # outer radius boundary[1]['outer'] = 2 # Definition of measures and normal vector: n = dolfin.FacetNormal(mesh) dx = dolfin.Measure("dx", mesh) ds = dolfin.Measure("ds", domain=mesh, subdomain_data=boundary[0]) else: width = inner height = outer mesh = dolfin.RectangleMesh(origin, Point(width, height), meshres[0], meshres[1]) mesh.init() boundary = (dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0), {}) for f in dolfin.facets(mesh): if dolfin.near(f.midpoint()[1], 0.): boundary[0][f] = 1 # bottom boundary[1]['bottom'] = 1 elif dolfin.near(f.midpoint()[1], height): boundary[0][f] = 2 # top boundary[1]['top'] = 2 elif dolfin.near(f.midpoint()[0], 0.): boundary[0][f] = 3 # left boundary[1]['left'] = 3 elif dolfin.near(f.midpoint()[0], width): boundary[0][f] = 4 # right boundary[1]['right'] = 4 # Definition of measures and normal vector: n = dolfin.FacetNormal(mesh) dx = dolfin.Measure("dx", mesh) ds = dolfin.Measure("ds", subdomain_data=boundary[0]) return (mesh, boundary, n, dx, ds)
def facet_to_dof_map(V): '''facet index -> DLT0 dofs''' assert V.ufl_element().family() == 'HDiv Trace' assert V.ufl_element().degree() == 0 assert V.ufl_element().value_shape() == () dm = V.dofmap() mesh = V.mesh() cdim = mesh.topology().dim() fdim = cdim - 1 mesh.init(fdim, cdim) mesh.init(cdim, fdim) c2f = mesh.topology()(cdim, fdim) mapping = np.zeros(mesh.num_entities(fdim), dtype='uintp') for f in facets(mesh): c = f.entities(cdim)[0] cell_dofs = dm.cell_dofs(c) fid = f.index() dof = cell_dofs[c2f(c).tolist().index(fid)] mapping[fid] = dof return mapping
def convert_meshfunctions_to_submesh(mesh, submesh, meshfunctions_on_mesh): assert meshfunctions_on_mesh is None or (isinstance( meshfunctions_on_mesh, list) and len(meshfunctions_on_mesh) > 0) if meshfunctions_on_mesh is None: return None meshfunctions_on_submesh = list() # Create submesh subdomains for mesh_subdomain in meshfunctions_on_mesh: submesh_subdomain = MeshFunction("size_t", submesh, mesh_subdomain.dim()) submesh_subdomain.set_all(0) assert submesh_subdomain.dim() in (submesh.topology().dim(), submesh.topology().dim() - 1) if submesh_subdomain.dim() == submesh.topology().dim(): for submesh_cell in cells(submesh): submesh_subdomain.array()[ submesh_cell.index()] = mesh_subdomain.array()[ submesh.submesh_to_mesh_cell_local_indices[ submesh_cell.index()]] elif submesh_subdomain.dim() == submesh.topology().dim() - 1: for submesh_facet in facets(submesh): submesh_subdomain.array()[ submesh_facet.index()] = mesh_subdomain.array()[ submesh.submesh_to_mesh_facet_local_indices[ submesh_facet.index()]] else: # impossible to arrive here anyway, thanks to the assert raise TypeError( "Invalid arguments in convert_meshfunctions_to_submesh.") meshfunctions_on_submesh.append(submesh_subdomain) return meshfunctions_on_submesh
def mesh3d(width, depth, height, nx, ny, nz): mesh = dolfin.BoxMesh(Point(0., 0., 0.), Point(width, depth, height), nx, ny, nz) boundary = (dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0), {}) for f in dolfin.facets(mesh): if dolfin.near(f.midpoint()[2], 0.): boundary[0][f] = 1 # bottom boundary[1]['bottom'] = 1 elif dolfin.near(f.midpoint()[2], height): boundary[0][f] = 2 # top boundary[1]['top'] = 2 elif dolfin.near(f.midpoint()[0], 0.): boundary[0][f] = 3 # left boundary[1]['left'] = 3 elif dolfin.near(f.midpoint()[0], width): boundary[0][f] = 4 # right boundary[1]['right'] = 4 elif dolfin.near(f.midpoint()[1], 0): boundary[0][f] = 5 # front boundary[1]['front'] = 5 elif dolfin.near(f.midpoint()[1], depth): boundary[0][f] = 6 # back boundary[1]['back'] = 6 # Definition of measures and normal vector: n = dolfin.FacetNormal(mesh) dx = dolfin.Measure("dx", mesh) ds = dolfin.Measure("ds", subdomain_data=boundary[0]) mesh_xdmf = dolfin.XDMFFile(mpi_comm_world(), "data/mesh_3D.xdmf") mesh_xdmf.write(boundaries[0]) return (mesh, boundary, n, dx, ds)
def commonEdge(cell1, cell2, mesh): facets1 = facets(cell1) facets2 = facets(cell2) # find common index ind_fac1 = [] for facet in facets1: ind_fac1 = np.append(ind_fac1, facet.index()) ind_fac2 = [] for facet in facets2: ind_fac2 = np.append(ind_fac2, facet.index()) # intersect gives index index = np.intersect1d(ind_fac1, ind_fac2) return Facet(mesh, int(index[0]))
def write_fenics_file(ofile, mesh, editor): dim = mesh.geometry().dim() for i in range(1, len(cell_map)+1): if dim == 2: editor.add_cell(i-1, cell_map[i][0]-1, cell_map[i][1]-1, cell_map[i][2]-1) else: editor.add_cell(i-1, cell_map[i][0]-1, cell_map[i][1]-1, cell_map[i][2]-1, cell_map[i][3]-1) mesh.order() # Set MeshValueCollections from info in boundary_cell #mvc = mesh.domains().markers(dim-1) md = mesh.domains() for zone, cells in boundary_cells.iteritems(): for cell, nds in cells.iteritems(): dolfin_cell = Cell(mesh, cell-1) vertices_of_cell = dolfin_cell.entities(0) vertices_of_face = nds - 1 for jj, ff in enumerate(facets(dolfin_cell)): facet_vertices = ff.entities(0) if all(map(lambda x: x in vertices_of_face, facet_vertices)): local_index = jj break #mvc.set_value(cell-1, local_index, zone) md.set_marker((ff.index(), zone), dim-1) ofile << mesh from dolfin import plot plot(mesh, interactive=True) print 'Finished writing FEniCS mesh\n'
def hat_function_grad(vertex, cell): """Compute L^\infty-norm of gradient of hat function on 'cell' and value 1 in 'vertex'.""" # TODO: fix using ghosted mesh not_working_in_parallel("function 'hat_function_grad'") assert vertex in vertices(cell), "vertex not in cell!" # Find adjacent facet f = [f for f in facets(cell) if not vertex in vertices(f)] assert len(f) == 1, "Something strange with adjacent cell!" f = f[0] # Get unit normal n = f.normal() n /= n.norm() # Pick some vertex on facet # FIXME: Is it correct index in parallel? facet_vertex_0 = Vertex(cell.mesh(), f.entities(0)[0]) # Compute signed distance from vertex to facet plane d = (facet_vertex_0.point() - vertex.point()).dot(n) # Return norm of gradient assert d != 0.0, "Degenerate cell!" return 1.0/abs(d)
def set_mesh(self, mesh, *, transform=None): mesh.init() self.mesh = mesh self.basedim = mesh.geometric_dimension() self.num_vertices = mesh.num_vertices() self.num_cells = mesh.num_cells() self.num_facets = mesh.num_facets() self.dimension_dict = { self.num_cells: self.basedim, self.num_facets: self.basedim - 1 } if transform is None: self.file.create_dataset('vertices', (self.num_vertices, self.basedim), data=mesh.coordinates(), compression=self.compression) else: self.file.create_dataset('vertices', (self.num_vertices, self.basedim), data=transform(mesh.coordinates()), compression=self.compression) self.file.create_dataset('cells', (self.num_cells, self.basedim + 1), data=numpy.array(mesh.cells(), dtype=numpy.uintp), compression=self.compression) self.file.create_dataset( 'facets', (self.num_facets, self.basedim), data=numpy.array( [facet.entities(0) for facet in dolfin.facets(mesh)], dtype=numpy.uintp), compression=self.compression)
def get_vertex_patch(vid, mesh, layers=1): # find patch cells patch_cid = [] for l in range(layers): if l == 0: patch_cid = Vertex(mesh,vid).entities(2).tolist() else: new_cid = [] for cid in patch_cid: for cid in Cell(mesh,cid).entities(2).tolist(): if cid not in patch_cid: new_cid.append(cid) patch_cid = patch_cid + new_cid # determine all facets FF_inner = FacetFunction('size_t', mesh) inner_facets = [Cell(mesh,cid).entities(1).tolist() for cid in patch_cid] inner_facets = set(iter.chain(*inner_facets)) for fid in inner_facets: FF_inner[int(fid)] = 1 # determine boundary facets FF_boundary = FacetFunction('size_t', mesh) for cid in patch_cid: c = Cell(mesh,cid) for f in facets(c): flist = f.entities(2).tolist() for fcid in flist: if fcid not in patch_cid or len(flist)==1: FF_boundary[f.index()] = 1 FF_inner[f.index()] = 2 if len(flist)==2 else 3 # mark patch boundary facet (3 for outer Dirichlet boundary) break return patch_cid, FF_inner, FF_boundary
def calculate_normal(self, domains, interior, exterior): """calculate normal pointing towards the exterior domain at the middle of each facet. Return the normal and its position """ self.normal = np.zeros((self.Nfacets, 2)) self.midpoints = np.zeros((self.Nfacets, 2)) self.facet_lengths = np.zeros(self.Nfacets) counter = 0 for facet in facets(domains.mesh()): cells = facet.entities(2) if facet.exterior() == False: domain1 = domains.array()[cells[0]] domain2 = domains.array()[cells[1]] if (sorted([domain1, domain2]) == sorted([interior, exterior])): self.facet_lengths[counter] = facet_length(facet) if domain1 == interior: self.normal[counter, 0] = facet.normal().x() self.normal[counter, 1] = facet.normal().y() self.midpoints[counter, 0] = facet.midpoint().x() self.midpoints[counter, 1] = facet.midpoint().y() elif domain1 == exterior: self.normal[counter, 0] = -facet.normal().x() self.normal[counter, 1] = -facet.normal().y() self.midpoints[counter, 0] = facet.midpoint().x() self.midpoints[counter, 1] = facet.midpoint().y() counter += 1 return (self.normal, self.midpoints)
def compute_parent_facet_indices(submesh, mesh): dim = mesh.topology().dim() facet_dim = dim - 1 submesh.init(facet_dim) mesh.init(facet_dim) # Make sure we have vertex-facet connectivity for parent mesh mesh.init(0, facet_dim) parent_vertex_indices = submesh.data().array("parent_vertex_indices", 0) # Create the fact map parent_facet_indices = np.full(submesh.num_facets(), -1) # Iterate over the edges and figure out their parent number for local_facet in df.facets(submesh): # Get parent indices for edge vertices vs = local_facet.entities(0) Vs = [df.Vertex(mesh, parent_vertex_indices[int(v)]) for v in vs] # Get outgoing facets from the two parent vertices facets = [set(V.entities(facet_dim)) for V in Vs] # Check intersection common_facets = facets[0] for f in facets[1:]: common_facets = common_facets.intersection(f) assert len(common_facets) == 1 parent_facet_index = list(common_facets)[0] # Set value parent_facet_indices[local_facet.index()] = parent_facet_index return parent_facet_indices
def fun(mesh2d, nselects): '''A random curve from the edges''' import networkx as nx import random facet_f = df.MeshFunction('size_t', mesh2d, 1, 0) mesh2d.init(1, 0) # Init the graph G = nx.Graph() edge_indices = { tuple(sorted(facet.entities(0).tolist())): f_index for f_index, facet in enumerate(df.facets(mesh2d)) } G.add_edges_from(iter(edge_indices.keys())) vertices = list(range(mesh2d.num_vertices())) for _ in range(nselects): v0, v1 = random.sample(vertices, 2) if v0 == v1: continue # THe path is a shortest path between 2 random vertices path = nx.shortest_path(G, source=v0, target=v1) for v0, v1 in zip(path[:-1], path[1:]): edge = (v0, v1) if v0 < v1 else (v1, v0) facet_f[edge_indices[edge]] = 1 return facet_f
def fun(mesh2d, nselects): '''A random curve from the edges''' import networkx as nx import random facet_f = df.MeshFunction('size_t', mesh2d, 1, 0) mesh2d.init(1, 0) # Init the graph G = nx.Graph() edge_indices = {tuple(sorted(facet.entities(0).tolist())): f_index for f_index, facet in enumerate(df.facets(mesh2d))} G.add_edges_from(edge_indices.iterkeys()) vertices = range(mesh2d.num_vertices()) for _ in range(nselects): v0, v1 = random.sample(vertices, 2) if v0 == v1: continue # THe path is a shortest path between 2 random vertices path = nx.shortest_path(G, source=v0, target=v1) for v0, v1 in zip(path[:-1], path[1:]): edge = (v0, v1) if v0 < v1 else (v1, v0) facet_f[edge_indices[edge]] = 1 return facet_f
def offsets_to_facetfunction(function, out_ff=None): ''' Parameters ---------- function : dolfin.Function Input DG0 function. Returns ------- ff : dolfin.MeshFunction Facet function: equal to 1 if facet separates two cells with different `function` values, and 0 otherwise. ''' space = function.function_space() mesh = space.mesh() D = mesh.geometry().dim() vec = function.vector() ff = out_ff if not ff: ff = dolfin.MeshFunction("int", mesh, D - 1, 0) ffv = ff.array() for facet in dolfin.facets(mesh): l = facet.entities(D) if len(l) == 2: a, b = l if vec[a] != vec[b]: ffv[facet.index()] = 1 return ff
def boundaries(mesh): boundaries = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0) for f in facets(mesh): boundaries.array()[f.index()] = 0 for v in vertices(f): boundaries.array()[f.index()] += v.global_index() return boundaries
def from_mesh(cls, mesh, initial_point, k): print 'Creating Mesh from dolfin.Mesh data.' # Make sure it is the right kind of mesh. print 'Initializing mesh attributes (edges, faces, etc.)' mesh.init() # This will do nothing if already called. check_mesh_type(mesh) # Compute extra data not stored on the object. print 'Reading vertex list from the mesh object' vertex_list = list(dolfin.vertices(mesh)) print 'Reading edge list from the mesh object' edge_list = list(dolfin.edges(mesh)) print 'Reading facets list from the mesh object' # Use facets since they have facet.exterior() set. facets_list = list(dolfin.facets(mesh)) # Get values specific to motion on the mesh. print 'Reading cell list from the mesh object' cell_list = list(dolfin.cells(mesh)) initial_face_index = get_face(dolfin.Point(*initial_point), mesh, cell_list) print 'Parsing exterior faces and creating Face objects' (all_vertices, triangles, face_local_bases, neighbor_faces, initial_face_index) = get_face_data(vertex_list, edge_list, facets_list, initial_face_index) return cls(k, initial_point, initial_face_index, all_vertices, triangles, face_local_bases, neighbor_faces)
def write_fenics_file(ofile, mesh, editor): dim = mesh.geometry().dim() for i in range(1, len(cell_map) + 1): if dim == 2: editor.add_cell(i - 1, cell_map[i][0] - 1, cell_map[i][1] - 1, cell_map[i][2] - 1) else: editor.add_cell(i - 1, cell_map[i][0] - 1, cell_map[i][1] - 1, cell_map[i][2] - 1, cell_map[i][3] - 1) mesh.order() # Set MeshValueCollections from info in boundary_cell #mvc = mesh.domains().markers(dim-1) md = mesh.domains() for zone, cells in boundary_cells.iteritems(): for cell, nds in cells.iteritems(): dolfin_cell = Cell(mesh, cell - 1) vertices_of_cell = dolfin_cell.entities(0) vertices_of_face = nds - 1 for jj, ff in enumerate(facets(dolfin_cell)): facet_vertices = ff.entities(0) if all(map(lambda x: x in vertices_of_face, facet_vertices)): local_index = jj break #mvc.set_value(cell-1, local_index, zone) md.set_marker((ff.index(), zone), dim - 1) ofile << mesh from dolfin import plot plot(mesh, interactive=True) print 'Finished writing FEniCS mesh\n'
def precompute_facet_data(simulation): """ Get facet normal and areas in an easy to use format """ mesh = simulation.data['mesh'] conFC = simulation.data['connectivity_FC'] ndim = simulation.ndim cell_info = simulation.data['cell_info'] # Get the facet areas from the cells areas = {} for cell in dolfin.cells(mesh, 'all'): # Get the connected facets facet_idxs = cell.entities(ndim - 1) # Loop over connected facets and get the area for i, fidx in enumerate(facet_idxs): a = cell.facet_area(i) if fidx in areas: assert a == areas[fidx] else: areas[fidx] = a # Loop over facets and gather the required information facet_info = [None] * mesh.num_facets() for facet in dolfin.facets(mesh, 'all'): fidx = facet.index() mp = facet.midpoint() if ndim == 2: midpoint = numpy.array([mp.x(), mp.y()], float) else: midpoint = numpy.array([mp.x(), mp.y(), mp.z()], float) # Find one cell connected to this facet. There can be one or two # connected cells, we only need the first one connected_cells = conFC(fidx) icell0 = connected_cells[0] on_boundary = len(connected_cells) == 1 # Midpoint of local cell 0 cell0_mp = cell_info[icell0].midpoint # Vector from local cell midpoint to face midpoint vec0 = midpoint - cell0_mp # Find a normal pointing out from cell 0 normalpt = facet.normal() if ndim == 2: normal = numpy.array([normalpt.x(), normalpt.y()], float) else: normal = numpy.array([normalpt.x(), normalpt.y(), normalpt.z()], float) if numpy.dot(vec0, normal) < 0: normal *= -1 area = areas[fidx] facet_info[fidx] = FacetInfo(area, midpoint, normal, on_boundary) simulation.data['facet_info'] = facet_info
def get_dof_region_marks(simulation, V): """ Given a function space, return a dictionary mapping dof number to a list of region number (indexed from 0, same as region list from the input file). Many dofs will not be included in the mapping since they are not inside a boundary region (not on a boundary facet). This property is used elsewhere to identify boundary dofs, in mark_cell_layers() and in SlopeLimiterBoundaryConditions """ # This function only supports a small subset of function spaces family = V.ufl_element().family() assert family in ('Lagrange', 'Discontinuous Lagrange') # Get local indices for the facet dofs for each facet in the cell facet_dof_indices = get_facet_dof_indices(V) # Get dofs that share the same location (relevant for DG) same_loc_dofs = get_same_loc_dofs(V) # Loop over mesh and get dofs that are connected to boundary regions dm = V.dofmap() facet_marks = [int(m) for m in simulation.data['boundary_marker'].array()] mesh = simulation.data['mesh'] dof_region_marks = {} for cell in dolfin.cells(mesh, 'all'): dofs = dm.cell_dofs(cell.index()) for ifacet, facet in enumerate(dolfin.facets(cell)): # Get facet region marker mark = facet_marks[facet.index()] - 1 # Skip non-boundary facets if mark == -1: continue facet_dofs = dofs[facet_dof_indices[ifacet]] for fdof in facet_dofs: dof_region_marks.setdefault(fdof, []).append(mark) # Treat all dofs in the same location in the same way for fdof, regions in list(dof_region_marks.items()): for dof2 in same_loc_dofs[fdof]: if dof2 not in dof_region_marks: dof_region_marks[dof2] = regions continue for mark in regions: if mark not in dof_region_marks[dof2]: dof_region_marks[dof2].append(mark) # Order must be the same on all ranks independent of iteration order # of the dof_region_marks dictionary in the above loop for marks in dof_region_marks.values(): marks.sort() return dof_region_marks
def get_boundary_surface(simulation, field, value): """ Find the boundary surface consisting of facets with scalar field values greater than the given iso value """ assert simulation.ndim == 2 mesh = simulation.data['mesh'] all_values = field.compute_vertex_values() connectivity_FC = simulation.data['connectivity_FC'] # Find the crossing points where the contour crosses a facet connections = {} for facet in dolfin.facets(mesh): fid = facet.index() # Skip facets that are not on the boundary connected_cells = connectivity_FC(fid) if not len(connected_cells) == 1: continue # Get connected vertices and the field values there vertex_coords = [] vertex_values = [] for vertex in dolfin.vertices(facet): pt = vertex.point() vertex_coords.append((pt.x(), pt.y(), pt.z())) vertex_values.append(all_values[vertex.index()]) assert len(vertex_coords) == 2 # Check if all values are above the iso value if vertex_values[0] < value or vertex_values[1] < value: continue connections.setdefault(vertex_coords[0], []).append(vertex_coords[1]) connections.setdefault(vertex_coords[1], []).append(vertex_coords[0]) # Map coord to coord, just to be able to use the generic functionality in # contour_lines_from_endpoints which works on facet_id <-> coord mappings available_coords = {vc: vc for vc in connections} # Make continous contour lines # Find end points of contour lines and start with these end_points = [ vc for vc, neighbours in connections.items() if len(neighbours) < 2 ] contours_from_endpoints = contour_lines_from_endpoints( end_points, available_coords, connections) # Include crossing points without neighbours or joined circles without end points other_points = available_coords.keys() contours_from_singles_and_loops = contour_lines_from_endpoints( other_points, available_coords, connections) assert len(available_coords) == 0 return contours_from_endpoints + contours_from_singles_and_loops
def test_normal(): "Test that the normal() method is wrapped" mesh = UnitSquareMesh(4, 4) for facet in facets(mesh): n = facet.normal() nx, ny, nz = n.x(), n.y(), n.z() assert isinstance(nx, float) assert isinstance(ny, float) assert isinstance(nz, float)
def extract_coupling_boundary_vertices1(self, function_space): """Extracts verticies which lay on the boundary. Currently handles 2D case properly, 3D is circumvented. :raise Exception: if no correct coupling interface is defined :return: stack of verticies """ n = 0 local_dofs = [] vertices_x = [] vertices_y = [] if self._dimensions == 3: vertices_z = [] con = [] if not issubclass(type(self._coupling_subdomain), SubDomain): raise Exception("no correct coupling interface defined!") mesh = function_space.mesh() v2d = vertex_to_dof_map(function_space) value_size = function_space.ufl_element().value_size() for f in facets(mesh): interface = True #if f.exterior(): for v in vertices(f): if self._dimensions == 2: if not self._coupling_subdomain.inside( [v.x(0), v.x(1)], True): interface = False elif self._dimensions == 3: if not self._coupling_subdomain.inside( [v.x(0), v.x(1), v.x(2)], True): interface = False #else: # interface=False if interface: for v in vertices(f): for ii in range(value_size): local_dof = v2d[value_size * v.index() + ii] if ii == 0: con.append(local_dof) if local_dof not in local_dofs: local_dofs.append(local_dof) if ii == 0: n += 1 vertices_x.append(v.x(0)) vertices_y.append(v.x(1)) if self._dimensions == 3: vertices_z.append(v.x(2)) if self._dimensions == 2: return np.column_stack([vertices_x, vertices_y]), n, local_dofs, con elif self._dimensions == 3: return np.column_stack([vertices_x, vertices_y, vertices_z]), n, local_dofs, con
def mark_facets(mesh, ffun): """ Mark mesh according to facet function """ for facet in df.facets(mesh): if ffun[facet] == 2 ** 64 - 1: ffun[facet] = 0 mesh.domains().set_marker((facet.index(), ffun[facet]), 2)
def refine_perimeter(mesh): """Refine largest boundary triangles.""" mesh.init(1, 2) perimeter = [c for c in cells(mesh) if any([f.exterior() for f in facets(c)])] marker = CellFunction('bool', mesh, False) max_size = max([c.diameter() for c in perimeter]) for c in perimeter: marker[c] = c.diameter() > 0.75 * max_size return refine(mesh, marker)
def boundary_normal(mesh, facet_markers, bndry_id): """ Extracts the normal vector of the boundary marked by the boundary id by checking that 1. the facet normal vectors are co-linear 2. the vector connecting two face midpoints is tangential to both normal vectors. Returns a tuple of float representing the normal. """ assert isinstance(mesh, dlfn.Mesh) assert isinstance(facet_markers, dlfn.cpp.mesh.MeshFunctionSizet) assert isinstance(bndry_id, int) tol = 1.0e3 * dlfn.DOLFIN_EPS normal_vectors = [] midpoints = [] for f in dlfn.facets(mesh): if f.exterior(): if facet_markers[f] == bndry_id: current_normal = f.normal() current_midpoint = f.midpoint() for normal, midpoint in zip(normal_vectors, midpoints): # check that normal vectors point in the same direction assert current_normal.dot(normal) > 0.0 # check that normal vector are parallel if abs(current_normal.dot(normal) - 1.0) > tol: # pragma: no cover raise ValueError( "Boundary facets do not share common normal.") # compute a tangential vector as connection vector of two # midpoints midpoint_connection = midpoint - current_midpoint # check that tangential vector is orthogonal to both normal # vectors if abs(midpoint_connection.dot( normal)) > tol: # pragma: no cover raise ValueError( "Midpoint connection vector is not tangential to boundary facets." ) if abs(midpoint_connection.dot( current_normal)) > tol: # pragma: no cover raise ValueError( "Midpoint connection vector is not tangential to boundary facets." ) normal_vectors.append(current_normal) midpoints.append(current_midpoint) assert len(normal_vectors) > 0, "Boundary id is not marked in MeshFunction" assert len(midpoints) == len(normal_vectors) dim = mesh.topology().dim() normal = normal_vectors[0] return tuple(normal[d] for d in range(dim))
def refine_perimeter(mesh): """Refine largest boundary triangles.""" mesh.init(1, 2) perimeter = [ c for c in cells(mesh) if any([f.exterior() for f in facets(c)]) ] marker = CellFunction('bool', mesh, False) max_size = max([c.diameter() for c in perimeter]) for c in perimeter: marker[c] = c.diameter() > 0.75 * max_size return refine(mesh, marker)
def _check_boundary_conditions(self, bcs): from boundary_conditions import VelocityBCType, TemperatureBCType # input check: boundary conditions assert isinstance(bcs, dict) assert bcs.has_key("temperature") assert bcs.has_key("velocity") # check if structure of dictionary is correct ids_bc = set() for key, bc in bcs.iteritems(): if key is "velocity": bc_types = VelocityBCType none_type = VelocityBCType.no_slip elif key is "temperature": bc_types = TemperatureBCType none_type = None else: raise ValueError() const_type = bc_types.constant assert isinstance(bc, tuple) assert len(bc) > 0 # check sub boundary conditions for i in range(len(bc)): assert isinstance(bc[i], tuple) assert len(bc[i]) == 3 # check if type of bc is correct assert bc[i][0] in bc_types # check if type of facet_id is correct assert isinstance(bc[i][1], int) and bc[i][1] > 0 ids_bc.add(bc[i][1]) # check if value type of bc is correct if none_type is VelocityBCType.no_slip: assert bc[i][2] is None elif bc[i][2] is const_type: if key is "velocity": assert isinstance(bc[i][2], (list, tuple)) assert len(bc[i][2]) == self._space_dim assert all(isinstance(x, float) for x in bc[i][2]) elif key is "temperature": assert isinstance(bc[i][2], float) else: isinstance(bc[i][2], dlfn.Expression) # check if facet_ids of bcs occur in markers ids_bc = tuple(ids_bc) ids_bc_found = [ False, ] * len(ids_bc) for facet in dlfn.facets(self._mesh): if facet.exterior(): if self._facet_markers[facet] in ids_bc: i = ids_bc.index(self._facet_markers[facet]) ids_bc_found[i] = True if all(ids_bc_found): break
def _plot_edges(self, ax, mesh, edge_color, bdr_edge_color): 'Compute inner and boundary edges of the mesh and plot them.' # Create edges tdim = mesh.topology().dim() mesh.init(1) bdr_edges = set([]) # Compute boundary edges for inter-process boundaries if self.mpi_size > 1: # Facet cell connectivity, 2d = edge->cell, 3d = facet->cell mesh.init(tdim-1, tdim) # In 2d bdr edge has different number of local and global cells if tdim == 2: bdr_edges =\ set([f.index() for f in facets(mesh) if f.num_entities(tdim) != f.num_global_entities(tdim)]) # In 3d bdr edge belongs to facet who has different number of local # and global cells else: # Face -> edge connectivity mesh.init(tdim-1, 1) bdr_edges =\ set(map(int, sum([f.entities(1).tolist() for f in facets(mesh) if f.num_entities(tdim) != f.num_global_entities(tdim)], []))) # Plot inner_edges inner_edges = set(range(mesh.size(1))) - bdr_edges x_min_max =\ self._plot_edges_from_list(ax, mesh, inner_edges, edge_color) # Plot boundary edges if bdr_edges: self._plot_edges_from_list(ax, mesh, bdr_edges, bdr_edge_color) return x_min_max
def _plot_edges(self, ax, mesh, edge_color, bdr_edge_color): 'Compute inner and boundary edges of the mesh and plot them.' # Create edges tdim = mesh.topology().dim() mesh.init(1) bdr_edges = set([]) # Compute boundary edges for inter-process boundaries if self.mpi_size > 1: # Facet cell connectivity, 2d = edge->cell, 3d = facet->cell mesh.init(tdim - 1, tdim) # In 2d bdr edge has different number of local and global cells if tdim == 2: bdr_edges =\ set([f.index() for f in facets(mesh) if f.num_entities(tdim) != f.num_global_entities(tdim)]) # In 3d bdr edge belongs to facet who has different number of local # and global cells else: # Face -> edge connectivity mesh.init(tdim - 1, 1) bdr_edges =\ set(map(int, sum([f.entities(1).tolist() for f in facets(mesh) if f.num_entities(tdim) != f.num_global_entities(tdim)], []))) # Plot inner_edges inner_edges = set(range(mesh.size(1))) - bdr_edges x_min_max =\ self._plot_edges_from_list(ax, mesh, inner_edges, edge_color) # Plot boundary edges if bdr_edges: self._plot_edges_from_list(ax, mesh, bdr_edges, bdr_edge_color) return x_min_max
def extract_all_boundary_markers(mesh, mesh_function): """ Stores all boundary markers of the MeshFunction inside a set. """ assert isinstance(mesh, dlfn.Mesh) assert isinstance( mesh_function, (dlfn.cpp.mesh.MeshFunctionSizet, dlfn.cpp.mesh.MeshFunctionInt)) boundary_markers = set() for f in dlfn.facets(mesh): if f.exterior(): boundary_markers.add(mesh_function[f]) return boundary_markers
def cell_to_cells_adjacency_via_facet(self): mesh = self.mesh D = mesh.topology().dim() mesh.init(D - 1, D) mesh.init(D, D) cell_neighbors = [[] for i in range(mesh.num_cells())] for facet in dolfin.facets(mesh): l = facet.entities(D) if len(l) == 2: a, b = l cell_neighbors[a].append(b) cell_neighbors[b].append(a) return cell_neighbors
def boundary_mesh_entities(mesh, dim='facet', type='exterior', order=True): '''iterator of facets or cells of BoundaryMesh slow stupid limited workaround version >_< ''' if (dim, type, order) != ('facet', 'exterior', True): raise AssertionError() D = mesh.topology().dim() Facet = dolfin.Facet for f in dolfin.facets(mesh): if len(f.entities(D)) == 1: # only one adjacent cell, other side is nonexistence yield f
def init_localizer(self, bnd): # self.facet_adjacents[cell_id][facet_number] is the id of the adjacent cell # self.facet_normals[cell_id][facet_number] is the normal vector to a facet # self.facet_mids[cell_id][facet_number] is the midpoint on a facet # facet_number is a number from 0 to t_dim # TBD: Now all facets are stored redundantly (for each cell) # Storage could be reduced, but would the performance hit be significant? self.mesh.init(self.t_dim-1, self.t_dim) self.facet_adjacents = [] self.facet_normals = [] self.facet_mids = [] facets = list(df.facets(self.mesh)) for cell in df.cells(self.mesh): facet_ids = cell.entities(self.t_dim-1) adjacents = [] normals = [] mids = [] for facet_number, facet_id in enumerate(facet_ids): facet = facets[facet_id] adjacent = set(facet.entities(self.t_dim))-{cell.index()} adjacent = list(adjacent) if adjacent == []: # Travelled out of bounds through the following boundary # Minus indicates through boundary adjacent = -int(bnd.array()[facet_id]) else: adjacent = int(adjacent[0]) assert isinstance(adjacent,int) # take normal from cell rather than from facet to make sure it # is outwards-pointing normal = cell.normal(facet_number).array()[:self.g_dim] mid = facet.midpoint() mid = np.array([mid.x(), mid.y(), mid.z()]) mid = mid[:self.t_dim] adjacents.append(adjacent) normals.append(normal) mids.append(mid) self.facet_adjacents.append(adjacents) self.facet_normals.append(normals) self.facet_mids.append(mids)
def get_data(resolution): mesh_full_filename = 'data/mesh_res_%d_full.xml' % resolution mesh_3d_full = dolfin.Mesh(mesh_full_filename) print 'Calling mesh.init() to compute faces / edges / etc.' print '=' * 60 mesh_3d_full.init() print 'Reading facet, edge and vertex iterators into lists' print '=' * 60 facets = list(dolfin.facets(mesh_3d_full)) edges = list(dolfin.edges(mesh_3d_full)) vertices = list(dolfin.vertices(mesh_3d_full)) return mesh_3d_full, facets, edges, vertices
def base_mean_position(self): """ Return mean coordinates of the base (serial only?) """ import numpy as np (facet_indices,) = np.where(self.ffun.array() == self.markers["BASE"][0]) point_inidces = [] for facet in dolfin.facets(self.mesh): if facet.index() in facet_indices: point_inidces.extend(facet.entities(0).tolist()) return np.mean(self.mesh.coordinates()[point_inidces, :], 0)
def poincare_friedrichs_cutoff(o, p): if isinstance(o, Mesh): # TODO: easy fix - ghosted mesh + missing reduction not_working_in_parallel("PF cutoff on mesh") return max(poincare_friedrichs_cutoff(v, p) for v in vertices(o)) if isinstance(o, Vertex): # TODO: fix using ghosted mesh not_working_in_parallel("PF cutoff on patch") hat_fun_grad = max(hat_function_grad(o, c) for c in cells(o)) if any(f.exterior() for f in facets(o)): return 1.0 + friedrichs_const(o, p) * hat_fun_grad else: return 1.0 + poincare_const(o, p) * hat_fun_grad raise NotImplementedError
def get_face(point, mesh, cell_list): face_intersection = dolfin.cpp.mesh.intersect(mesh, point) # Require a unique intersection. This is not actually necessary as some # points may lie on an edge / vertex or may not be on the mesh at all. if face_intersection.intersected_cells().size != 1: raise ValueError('Point does not intersect mesh in a unique cell.') cell_index = face_intersection.intersected_cells()[0] matched_cell = cell_list[cell_index] exterior_facets = [facet for facet in dolfin.facets(matched_cell) if facet.exterior()] if len(exterior_facets) != 1: print 'exterior_facets:', exterior_facets raise ValueError('Number of facets on cell marked exterior != 1.') return exterior_facets[0].index()
def findAdjacentCellInd(cell, mesh): adj_cells = [] D = mesh.topology().dim() # Build connectivity between facets and cells mesh.init(D - 1, D) # loop over edges for facet in facets(cell): # find all cells with edge facet # print facet.entities(D) adj_cells = np.append(adj_cells, facet.entities(D)) # delete doubles and the cell itself adj_cells = np.unique(adj_cells) adj_cells = adj_cells[adj_cells != cell.index()] return adj_cells
def computeEdgeCRDofArray(V, mesh, B=None): # dof map, dim_V = 2 * num_E num_E = mesh.num_facets() dofmap = V.dofmap() edgeCRDofArray = np.zeros((num_E, 2)) # loop over cells and fill array for k, cell in enumerate(cells(mesh)): # list of dof-indices for edges of the cell dofs = dofmap.cell_dofs(cell.index()) for i, facet in enumerate(facets(cell)): # print 'cell: %3g || i: %3g || facet: %3g || dof[i]: %3g' \ # % (cell.index(), i, facet.index(), dofs[i]) # corresponding DoFs (2 basisfct per edge) edgeCRDofArray[facet.index()] = [dofs[i], dofs[i+3]] # edgeCRDofArray[facet.index()] = [dofs[i], dofs[i]+1] # every interior edge visited twice but EGAL! return edgeCRDofArray
def write_fenics_file(dim, ofilename): ofile = File(ofilename + '.xml') mesh = Mesh() editor = MeshEditor() editor.open(mesh, dim, dim) editor.init_vertices(nodes.shape[1]) editor.init_cells(len(cell_map)) for i in range(nodes.shape[1]): if dim == 2: editor.add_vertex(i, nodes[0, i], nodes[1, i]) else: editor.add_vertex(i, nodes[0, i], nodes[1, i], nodes[2, i]) for i in range(1, len(cell_map)+1): if dim == 2: editor.add_cell(i-1, cell_map[i][0]-1, cell_map[i][1]-1, cell_map[i][2]-1) else: editor.add_cell(i-1, cell_map[i][0]-1, cell_map[i][1]-1, cell_map[i][2]-1, cell_map[i][3]-1) mesh.order() mvc = mesh.domains().markers(dim-1) for zone, cells in boundary_cells.iteritems(): for cell, nds in cells.iteritems(): dolfin_cell = Cell(mesh, cell-1) nodes_of_cell = dolfin_cell.entities(0) #print cell #print nodes_of_cell nodes_of_face = nds - 1 #print nodes_of_face for jj, ff in enumerate(facets(dolfin_cell)): facet_nodes = ff.entities(0) #print facet_nodes if all(map(lambda x: x in nodes_of_face, facet_nodes)): local_index = jj break mvc.set_value(cell-1, local_index, zone) ofile << mesh from dolfin import plot plot(mesh, interactive=True) print 'Finished writing FEniCS mesh\n'
def main(): resolution = 96 # 32 * 3 mesh_full_filename = 'data/mesh_res_%d_full.xml' % resolution mesh_3d_full = dolfin.Mesh(mesh_full_filename) print 'Calling mesh.init() to compute faces / edges / etc.' print '=' * 60 mesh_3d_full.init() coords = mesh_3d_full.coordinates() top_coords = np.nonzero( coords[:, 2] >= full_dendrite_mesh.TOP_CONE_TOP_Z - 0.001)[0] top_coords_set = set(top_coords) num_faces = mesh_3d_full.num_faces() num_facets = mesh_3d_full.num_facets() if num_faces != num_facets: raise ValueError('Expected tetrahedral mesh.') # Use facets instead of faces (though identical) because the # facet objects have .exterior() set. faces_as_facets = dolfin.facets(mesh_3d_full) exterior_face_indices = [] vertical_normal_faces = [] all_top_coords_faces = [] face_count = 0 print 'Looping through faces to find faces on tops of synapses' print '=' * 60 for face in faces_as_facets: face_count += 1 if face_count % 20000 == 0: print face_count, '/', num_faces # Only use exterior facets / faces. if not face.exterior(): continue else: exterior_face_indices.append(face.index()) # The vertical normal is (0, 0, 1) and we check the angle between # the normal and this vector v . (0, 0, 1) = v_z (dot product). theta = np.arccos(face.normal().z()) if np.allclose(theta, 0): vertical_normal_faces.append(face) # If every single index is one of the "top coordinate" indices. if set(face.entities(0)) <= top_coords_set: all_top_coords_faces.append(face) # First save the exterior face indices. # NOTE: We are 100% sure indices are computed the same upon reloading data # from XML file. This is relevant for face indices, since they are # not stored in the XML file. See # http://fenicsproject.org/qa/3233 # for details. exterior_face_filename = 'data/exterior_faces_res_%d_full.npz' % resolution print '=' * 60 print 'Saving to file:', exterior_face_filename print '%d exterior faces out of %d total faces.' % ( len(exterior_face_indices), num_faces) print '=' * 60 np.savez(exterior_face_filename, np.array(exterior_face_indices)) if vertical_normal_faces != all_top_coords_faces: raise ValueError('Top face classifications disagree.') # Indices for the faces will be the same if data loaded again. See above. face_index_matrix = np.vstack( [face.entities(0) for face in vertical_normal_faces]) faces_full_filename = 'data/faces_top_res_%d_full.npz' % resolution print '=' * 60 print 'Saving to file:', faces_full_filename print '=' * 60 np.savez(faces_full_filename, face_index_matrix) # Save the indices of the facets on the top. top_indices_filename = 'data/faces_top_indices_res_%d_full.npz' % resolution print '=' * 60 print 'Saving to file:', top_indices_filename print '=' * 60 top_indices = [facet.index() for facet in vertical_normal_faces] np.savez(top_indices_filename, np.array(top_indices))
innerinds = np.setdiff1d(range(V.dim()), bcinds) bcinds = np.setdiff1d(range(V.dim()), innerinds) # vector of -1 vvec = np.zeros(V.dim()) - 1 # set inner nodes to 1 vvec[innerinds] = 1 # assign to function v = dolfin.Function(V) v.vector().set_local(vvec) # Evaluate CR at midpoints mesh.init(1, 2) midpoints = np.array([np.array([facet.midpoint().x(), facet.midpoint().y()]) for facet in dolfin.facets(mesh) if facet.exterior()]) U = np.zeros(len(midpoints)) V = np.zeros_like(U) for i, mp in enumerate(midpoints): U[i], V[i] = v(mp) import matplotlib.tri as tri import matplotlib.pyplot as plt # Data for mesh mesh_coordinates = mesh.coordinates().reshape((-1, 2)) triangles = np.asarray([cell.entities(0) for cell in dolfin.cells(mesh)]) triangulation = tri.Triangulation(mesh_coordinates[:, 0], mesh_coordinates[:, 1], triangles)
def mortar_meshes(subdomains, markers, ifacet_iter=None, strict=True, tol=1E-14): ''' Let subdomains a cell function. We assume that domains (cells) marked with the given markers are adjecent and an interface can be defined between these domains which is a continuous curve. Then for each domain we create a (sub)mesh and a single interface mesh which holds a connectivity map of its cells to facets of the submeshes. The submeshes are returned as a list. The connectivity map is of the form submesh.id -> facets. The marking function f of the EmbeddedMesh that is the interface is colored such that f[color] is the interface of meshes (submeshes[m] for m color_map[color]). ''' assert len(markers) > 1 # Need a cell function mesh = subdomains.mesh() tdim = mesh.topology().dim() assert subdomains.dim() == tdim markers = list(markers) # For each facet we want to know which 2 cells share it tagged_iface = defaultdict(dict) if ifacet_iter is None: mesh.init(tdim-1) ifacet_iter = df.facets(mesh) mesh.init(tdim-1, tdim) for facet in ifacet_iter: cells = map(int, facet.entities(tdim)) if len(cells) > 1: c0, c1 = cells tag0, tag1 = subdomains[c0], subdomains[c1] if tag0 != tag1 and tag0 in markers and tag1 in markers: # A key of sorted tags if tag0 < tag1: key = (tag0, tag1) # The cells connected to facet order to match to tags value = (c0, c1) else: key = (tag1, tag0) value = (c1, c0) # A facet to 2 cells map for the facets of tagged pair tagged_iface[key][facet.index()] = value # order -> tagged keys color_to_tag_map = tagged_iface.keys() # Set to color which won't be encounred interface = df.MeshFunction('size_t', mesh, tdim-1, len(color_to_tag_map)) values = interface.array() # Mark facets corresponding to tagged pair by a color for color, tags in enumerate(color_to_tag_map): values[tagged_iface[tags].keys()] = color # Finally create an interface mesh for all the colors interface_mesh = EmbeddedMesh(interface, range(len(color_to_tag_map))) # Try to recogninze the meshes which violates assumptions by counting assert not strict or is_continuous(interface_mesh) # And subdomain mesh for each marker subdomain_meshes = {tag: EmbeddedMesh(subdomains, tag) for tag in markers} # Alloc the entity maps for the embedded mesh interface_map = {subdomain_meshes[tag].id(): [None]*interface_mesh.num_cells() for tag in markers} # THe maps are filled by the following idea. Using marking function # of interface mesh one cat get cells of that color and useing entity # map for (original) mesh map the cells to mesh facet. A color also # corresponds to a pair of tags which identifies the two meshes which # share the facet - facet connected to 2 cells one for each mesh. The # final step is to lean to map submesh cells to mesh cells # local submesh <- global of parent mesh sub_mesh_map = lambda tag: dict( (mesh_c, submesh_c) for submesh_c, mesh_c in enumerate(subdomain_meshes[tag].parent_entity_map[mesh.id()][tdim]) ) # Thec cell-cell connectivity of each submesh c2c = {tag: sub_mesh_map(tag) for tag in markers} # A connectivity of interface mesh cells to facets of global mesh c2f = interface_mesh.parent_entity_map[mesh.id()][tdim-1] for color, tags in enumerate(color_to_tag_map): # Precompute for the 2 tags submeshes = [subdomain_meshes[tag] for tag in tags] for cell in df.SubsetIterator(interface_mesh.marking_function, color): cell_index = cell.index() # The corresponding global cell facet facet = c2f[cell_index] # The two cells in global mesh numbering global_cells = tagged_iface[tags][facet] # Let's find the facet in submesh for tag, gc, submesh in zip(tags, global_cells, submeshes): # The map uses local cell local_cell = c2c[tag][gc] mesh_id = submesh.id() found = False for submesh_facet in df.facets(df.Cell(submesh, local_cell)): found = df.near(cell.midpoint().distance(submesh_facet.midpoint()), 0, tol) if found: interface_map[mesh_id][cell_index] = submesh_facet.index() break # Collapse to list; I want list indexing subdomain_meshes = np.array([subdomain_meshes[m] for m in markers]) color_map = [map(markers.index, tags) for tags in color_to_tag_map] # Parent in the sense that the colored piece of interface # could have been created from mesh interface_mesh.parent_entity_map.update( dict((k, {tdim-1: v}) for k, v in interface_map.items()) ) return subdomain_meshes, interface_mesh, color_map
def test_convert_triangle(self): # Disabled because it fails, see FIXME below # test no. 1 from dolfin import Mesh, MPI if MPI.num_processes() != 1: return fname = os.path.join("data", "triangle") dfname = fname+".xml" # Read triangle file and convert to a dolfin xml mesh file meshconvert.triangle2xml(fname, dfname) # Read in dolfin mesh and check number of cells and vertices mesh = Mesh(dfname) self.assertEqual(mesh.num_vertices(), 96) self.assertEqual(mesh.num_cells(), 159) # Clean up os.unlink(dfname) # test no. 2 from dolfin import MPI, Mesh, MeshFunction, \ edges, Edge, faces, Face, \ SubsetIterator, facets, CellFunction if MPI.num_processes() != 1: return fname = os.path.join("data", "test_Triangle_3") dfname = fname+".xml" dfname0 = fname+".attr0.xml" # Read triangle file and convert to a dolfin xml mesh file meshconvert.triangle2xml(fname, dfname) # Read in dolfin mesh and check number of cells and vertices mesh = Mesh(dfname) mesh.init() mfun = MeshFunction('double', mesh, dfname0) self.assertEqual(mesh.num_vertices(), 58) self.assertEqual(mesh.num_cells(), 58) # Create a size_t CellFunction and assign the values based on the # converted Meshfunction cf = CellFunction("size_t", mesh) cf.array()[mfun.array()==10.0] = 0 cf.array()[mfun.array()==-10.0] = 1 # Meassure total area of cells with 1 and 2 marker add = lambda x, y : x+y area0 = reduce(add, (Face(mesh, cell.index()).area() \ for cell in SubsetIterator(cf, 0)), 0.0) area1 = reduce(add, (Face(mesh, cell.index()).area() \ for cell in SubsetIterator(cf, 1)), 0.0) total_area = reduce(add, (face.area() for face in faces(mesh)), 0.0) # Check that all cells in the two domains are either above or below y=0 self.assertTrue(all(cell.midpoint().y()<0 for cell in SubsetIterator(cf, 0))) self.assertTrue(all(cell.midpoint().y()>0 for cell in SubsetIterator(cf, 1))) # Check that the areas add up self.assertAlmostEqual(area0+area1, total_area) # Measure the edge length of the two edge domains edge_markers = mesh.domains().facet_domains() self.assertTrue(edge_markers is not None) length0 = reduce(add, (Edge(mesh, e.index()).length() \ for e in SubsetIterator(edge_markers, 0)), 0.0) length1 = reduce(add, (Edge(mesh, e.index()).length() \ for e in SubsetIterator(edge_markers, 1)), 0.0) # Total length of all edges and total length of boundary edges total_length = reduce(add, (e.length() for e in edges(mesh)), 0.0) boundary_length = reduce(add, (Edge(mesh, f.index()).length() \ for f in facets(mesh) if f.exterior()), 0.0) # Check that the edges add up self.assertAlmostEqual(length0+length1, total_length) self.assertAlmostEqual(length1, boundary_length) # Clean up os.unlink(dfname) os.unlink(dfname0)