def IcosahedralSphereMesh(level, layers): from dolfin import Mesh, MeshEditor, File # generate vertices and cells (vertices, cells) = generate_icoshedral_sphere_mesh( level, layers) # init mesh and mesh editor helper mesh = Mesh() editor = MeshEditor() editor.open(mesh, 3, 3); # add vertices to mesh nVert = len(vertices) editor.init_vertices(nVert) verts = vertices.items() #verts = sorted(verts, key=lambda key: key[1]) for v in verts: editor.add_vertex(v[1], v[0][0], v[0][1], v[0][2]) ncells = len(cells) editor.init_cells(ncells) id = 0 for c in cells: editor.add_cell(id, c[0], c[1], c[2], c[3]) id += 1 # done: create and return mesh object editor.close() return mesh
def get_original_mesh(t_mesh_path, mesh, par): def transform(coordinates, xi, rho): S = np.exp(coordinates[:, 0] + coordinates[:, 1] * rho / np.sqrt(1 - rho**2)) v = 50 * coordinates[:, 1] * xi / np.sqrt(1 - rho**2) new_coords = np.column_stack((S, v)) return new_coords if os.path.exists(t_mesh_path): t_mesh = Mesh() with XDMFFile(t_mesh_path) as f: f.read(t_mesh) return t_mesh # Construct the mesh under transformed variables new_coords = transform(mesh.coordinates(), xi=par.xi, rho=par.rho) t_mesh = Mesh() editor = MeshEditor() editor.open(t_mesh, 'triangle', 2, 2) editor.init_vertices(len(new_coords)) editor.init_cells(len(mesh.cells())) for i, vertex in enumerate(new_coords): editor.add_vertex(i, vertex) for i, cell in enumerate(mesh.cells()): editor.add_cell(i, cell) editor.close() with XDMFFile(t_mesh_path) as f: f.write(t_mesh) return t_mesh
def fit2d(x0, y0, points, cells, eps, degree=1, verbose=False, solver='spsolve'): # Convert points, cells to dolfin mesh editor = MeshEditor() mesh = Mesh() # topological and geometrical dimension 2 editor.open(mesh, 'triangle', 2, 2, 1) editor.init_vertices(len(points)) editor.init_cells(len(cells)) for k, point in enumerate(points): editor.add_vertex(k, point[:2]) for k, cell in enumerate(cells.astype(numpy.uintp)): editor.add_cell(k, cell) editor.close() # Eps = numpy.array([[eps, eps], [eps, eps]]) # Eps = numpy.array([[eps, 0], [0, eps]]) Eps = numpy.array([[2 * eps, eps], [eps, 2 * eps]]) # Eps = numpy.array([[1.0, 1.0], [1.0, 1.0]]) return fit(x0, y0, mesh, Eps, degree=degree, verbose=verbose, solver=solver)
def get(self): """Build mesh from the tree of triangles created by reflections.""" # get n n, k, a, b = self.pad(self.values) # adjust defaults based on n self.full[2:4] = self.shape[n] # get all parameters n, k, a, b = self.pad(self.values) if n == -1: self.vertices = self.bothvertices[k] else: tree = self.trees[(n, k)] self.triangles = [] # angles are 2pi/a, 2pi/b side = np.sin(2 * pi / b) / np.sin(pi - 2 * pi / a - 2 * pi / b) self.vertices = [ np.array([0.0, 0.0]), np.array([1.0, 0.0]), np.array( [side * np.cos(2 * pi / a), side * np.sin(2 * pi / a)])] self.generate(tree, [0, 1, 2]) mesh = Mesh() editor = MeshEditor() editor.open(mesh, 2, 2) editor.init_vertices(len(self.vertices)) editor.init_cells(len(self.triangles)) for i, v in enumerate(self.vertices): editor.add_vertex(i, *v) for i, t in enumerate(self.triangles): editor.add_cell(i, *t) editor.close() return mesh
def __setstate__(self, d): """pickling restore""" # mesh verts = d['coordinates'] elems = d['cells'] dim = verts.shape[1] mesh = Mesh() ME = MeshEditor() ME.open(mesh, dim, dim) ME.init_vertices(verts.shape[0]) ME.init_cells(elems.shape[0]) for i, v in enumerate(verts): ME.add_vertex(i, v[0], v[1]) for i, c in enumerate(elems): ME.add_cell(i, c[0], c[1], c[2]) ME.close() # function space if d['num_subspaces'] > 1: V = VectorFunctionSpace(mesh, d['family'], d['degree']) else: V = FunctionSpace(mesh, d['family'], d['degree']) # vector v = Function(V) v.vector()[:] = d['array'] self._fefunc = v
def get(self): """Build mesh from the tree of triangles created by reflections.""" # get n n, k, a, b = self.pad(self.values) # adjust defaults based on n self.full[2:4] = self.shape[n] # get all parameters n, k, a, b = self.pad(self.values) if n == -1: self.vertices = self.bothvertices[k] else: tree = self.trees[(n, k)] self.triangles = [] # angles are 2pi/a, 2pi/b side = np.sin(2 * pi / b) / np.sin(pi - 2 * pi / a - 2 * pi / b) self.vertices = [ np.array([0.0, 0.0]), np.array([1.0, 0.0]), np.array( [side * np.cos(2 * pi / a), side * np.sin(2 * pi / a)]) ] self.generate(tree, [0, 1, 2]) mesh = Mesh() editor = MeshEditor() editor.open(mesh, 2, 2) editor.init_vertices(len(self.vertices)) editor.init_cells(len(self.triangles)) for i, v in enumerate(self.vertices): editor.add_vertex(i, *v) for i, t in enumerate(self.triangles): editor.add_cell(i, *t) editor.close() return mesh
def mesh_gen_1d(layer_thickness, elem_per_layer): editor = MeshEditor() mesh = Mesh() editor.open(mesh, 1, 1) num_cells = sum(elem_per_layer) num_vertices = num_cells + 1 editor.init_vertices(num_vertices) # number of vertices editor.init_cells(num_cells) # number of cells editor.add_vertex(0, np.array([0.0])) vertex_index = 0 # Add vertices layer_startpos = np.cumsum([0] + layer_thickness) for i in range(len(layer_thickness)): dist = layer_thickness[i] / elem_per_layer[i] offset = layer_startpos[i] for k in range(elem_per_layer[i]): vertex_index += 1 editor.add_vertex(vertex_index, \ np.array([offset + dist * (k + 1)])) # Add cells for i in range(num_cells): editor.add_cell(i, np.array([i, i + 1], dtype=np.uintp)) editor.close() return mesh
def import_from_gmsh(fname): "Convert from gmsh to dolfin" # read with meshio msh = meshio.read(fname) # create a DOLFIN mesh (assuming 2d) gdim, tdim = 2, 2 mm = Mesh() editor = MeshEditor() editor.open(mm, "triangle", gdim, tdim) npt = msh.points.shape[0] nc = msh.get_cells_type("triangle").shape[0] editor.init_vertices_global(npt, npt) editor.init_cells_global(nc, nc) for i, p in enumerate(msh.points): editor.add_vertex(i, p[:2]) for i, c in enumerate(msh.get_cells_type("triangle")): editor.add_cell(i, c) editor.close() # domains md = mm.domains() md.init(tdim) markers = {} if 'gmsh:physical' not in msh.cell_data_dict: # no markers at all return mm, markers phy = msh.cell_data_dict['gmsh:physical'] if 'triangle' in phy: for eid, val in enumerate(phy['triangle']): md.set_marker((eid, val), 2) if 'line' in phy: mm.init(0, 1) p2e = mm.topology()(0, 1) for l, k in zip(msh.get_cells_type("line"), phy['line']): e = set(p2e(l[0])).intersection(p2e(l[1])).pop() md.set_marker((e, k), 1) if 'vertex' in phy: for eid, val in zip(msh.get_cells_type("vertex"), phy['vertex']): md.set_marker((eid[0], val), 0) # names markers = tuple( {n: v.item() for n, (v, d) in msh.field_data.items() if d == dim} for dim in range(tdim + 1)) return mm, markers
def create_dolfin_mesh(points, cells): # https://bitbucket.org/fenics-project/dolfin/issues/845/initialize-mesh-from-vertices editor = MeshEditor() mesh = Mesh() editor.open(mesh, "triangle", 2, 2) editor.init_vertices(points.shape[0]) editor.init_cells(cells.shape[0]) for k, point in enumerate(points): editor.add_vertex(k, point) for k, cell in enumerate(cells): editor.add_cell(k, cell) editor.close() return mesh
def _create_dolfin_mesh(points, cells): editor = MeshEditor() mesh = Mesh() # topological and geometrical dimension 2 editor.open(mesh, "triangle", 2, 2, 1) editor.init_vertices(len(points)) editor.init_cells(len(cells)) for k, point in enumerate(points): editor.add_vertex(k, point[:2]) for k, cell in enumerate(cells.astype(numpy.uintp)): editor.add_cell(k, cell) editor.close() return mesh
def Triangle(left, bottom): """ Triangular mesh with just one triangular cell. """ mesh = Mesh() editor = MeshEditor() editor.open(mesh, 2, 2) editor.init_vertices(3) editor.init_cells(1) editor.add_vertex(0, 0, 0) editor.add_vertex(1, bottom, 0) editor.add_vertex(2, 0, left) editor.add_cell(0, 0, 1, 2) editor.close() return mesh
def get(self): """Just one cell.""" topx, topy = self.pad(self.values) mesh = Mesh() editor = MeshEditor() editor.open(mesh, 2, 2) editor.init_vertices(3) editor.init_cells(1) editor.add_vertex(0, 0, 0) editor.add_vertex(1, 1, 0) editor.add_vertex(2, topx, topy) editor.add_cell(0, 0, 1, 2) editor.close() return mesh
def get(self): """One cell.""" mesh = Mesh() editor = MeshEditor() editor.open(mesh, 3, 3) editor.init_vertices(4) editor.init_cells(1) editor.add_vertex(0, 0, 0, 0) editor.add_vertex(1, 1, 1, 0) editor.add_vertex(2, 0, 1, 1) editor.add_vertex(3, 1, 0, 1) editor.add_cell(0, 0, 1, 2, 3) editor.close() return mesh
def get(self): """Single cell.""" a, b, c, d, e = self.pad(self.values) mesh = Mesh() editor = MeshEditor() editor.open(mesh, 3, 3) # dimension editor.init_vertices(4) editor.init_cells(1) editor.add_vertex(0, 0, 0, 0) editor.add_vertex(1, 1, 0, 0) editor.add_vertex(2, a, b, 0) editor.add_vertex(3, c, d, e) editor.add_cell(0, 0, 1, 2, 3) editor.close() return mesh
def get(self): """Two cells.""" a, b = self.pad(self.values) mesh = Mesh() editor = MeshEditor() editor.open(mesh, 2, 2) editor.init_vertices(4) editor.init_cells(2) editor.add_vertex(0, 0, 0) editor.add_vertex(1, 1, 0) editor.add_vertex(2, a, b) editor.add_vertex(3, a, -b) editor.add_cell(0, 0, 1, 2) editor.add_cell(1, 0, 1, 3) editor.close() return mesh
def fit2d(x0, y0, points, cells, lmbda, degree=1, solver="sparse"): # Convert points, cells to dolfin mesh editor = MeshEditor() mesh = Mesh() # topological and geometrical dimension 2 editor.open(mesh, "triangle", 2, 2, 1) editor.init_vertices(len(points)) editor.init_cells(len(cells)) for k, point in enumerate(points): editor.add_vertex(k, point[:2]) for k, cell in enumerate(cells.astype(numpy.uintp)): editor.add_cell(k, cell) editor.close() V = FunctionSpace(mesh, "CG", degree) return fit(x0, y0, V, lmbda, solver=solver)
def build_mesh_old(cells, vertices): """Assemble a mesh object from cells and vertices.""" mesh = Mesh() editor = MeshEditor() dim = len(vertices[0]) if dim == 2: editor.open(mesh, 'triangle', 2, 2) else: editor.open(mesh, 'tetrahedron', 3, 3) editor.init_vertices(len(vertices)) editor.init_cells(len(cells)) for i, v in enumerate(vertices): editor.add_vertex(i, *v) for i, c in enumerate(cells): editor.add_cell(i, *c) editor.close() return mesh
def get(self): """One triangle per side with common vertex at (0,0).""" sides = self.values[0] mesh = Mesh() editor = MeshEditor() editor.open(mesh, 2, 2) editor.init_vertices(sides + 1) editor.init_cells(sides) editor.add_vertex(0, 0, 0) for i in range(1, sides + 1): editor.add_vertex(i, cos(2 * pi * i / sides), sin(2 * pi * i / sides)) for i in range(sides - 1): editor.add_cell(i, 0, i + 1, i + 2) editor.add_cell(sides - 1, 0, sides, 1) editor.close() return mesh
def get(self): """Part of the regular polygon construction.""" sides, angle = self.pad(self.values) mesh = Mesh() editor = MeshEditor() editor.open(mesh, 2, 2) # dimension editor.init_vertices(angle + 2) editor.init_cells(angle) editor.add_vertex(0, 0, 0) for i in range(0, angle + 1): editor.add_vertex(i + 1, cos(2 * pi * i / sides), sin(2 * pi * i / sides)) editor.add_cell(0, 2, 1, 0) for i in range(1, angle): editor.add_cell(i, 0, i + 1, i + 2) editor.close() return mesh
def get_reference_element(dim=2): nodes, cell = get_reference_coordinates(dim) cells = np.atleast_2d(np.arange( dim + 1, dtype=np.uintp)) # connection of nodes (defines element) # this piece of code creates a mesh containing one element only mesh = Mesh() editor = MeshEditor() editor.open(mesh, cell, dim, dim) editor.init_vertices(dim + 1) editor.init_cells(1) for i, n in enumerate(nodes): p = Point(n) editor.add_vertex(i, p) for i, n in enumerate(cells): editor.add_cell(i, n) editor.close() return mesh
def get(self): """Build cells based on triangulated regular polygon.""" sides, h, x, y = self.pad(self.values) mesh = Mesh() editor = MeshEditor() editor.open(mesh, 3, 3) # dimension editor.init_vertices(sides + 2) editor.init_cells(sides) editor.add_vertex(0, x, y, h) for i in range(1, sides + 1): editor.add_vertex(i, cos(2 * pi * i / sides), sin(2 * pi * i / sides), 0) editor.add_vertex(sides + 1, 0, 0, 0) for i in range(sides - 1): editor.add_cell(i, 0, i + 1, i + 2, sides + 1) editor.add_cell(sides - 1, 0, sides, 1, sides + 1) editor.close() return mesh
def build_interval_mesh(vertices, cells): '''Mesh of 1d topology in n-dims.''' imesh = Mesh() editor = MeshEditor() editor.open(imesh, 1, vertices.shape[1]) editor.init_vertices(len(vertices)) editor.init_cells(len(cells)) # Add vertices for vertex_index, v in enumerate(vertices): editor.add_vertex(vertex_index, v) # Add cells for cell_index, (v0, v1) in enumerate(cells): editor.add_cell(cell_index, v0, v1) editor.close() return imesh
def main(): def round_trip_connect(start, end): result = [] for i in range(start, end): result.append((i, i+1)) result.append((end, start)) return result corners, mesh1, mesh2 = generate_meshes(2, 1, 0.3) points = get_vertices(corners, mesh1, mesh2) print "points", np.array(points) info = triangle.MeshInfo() info.set_points(points) info.set_facets(round_trip_connect(0, len(corners)-1)) mesh = triangle.build(info, allow_volume_steiner=False, allow_boundary_steiner=False, min_angle=60) if False: print "vertices:" for i, p in enumerate(mesh.points): print i, p print "point numbers in triangles:" for i, t in enumerate(mesh.elements): print i, t finemesh = Mesh() ME = MeshEditor() ME.open(finemesh,2,2) ME.init_vertices(len(mesh.points)) ME.init_cells(len(mesh.elements)) for i,v in enumerate(mesh.points): ME.add_vertex(i,v[0],v[1]) for i,c in enumerate(mesh.elements): ME.add_cell(i,c[0],c[1],c[2]) ME.close() triangle.write_gnuplot_mesh("triangles.dat", mesh) plot(mesh1) plot(mesh2) plot(finemesh) interactive()
def setUp(self, *args, **kwargs): self.mesh = Mesh() editor = MeshEditor() editor.open(self.mesh, 2, 2) # topo_dim = 2, geom dim = 2 editor.init_vertices(6) editor.init_cells(2) vertex_0 = Vertex(self.mesh, 0) vertex_1 = Vertex(self.mesh, 1) vertex_2 = Vertex(self.mesh, 2) vertex_3 = Vertex(self.mesh, 3) vertex_4 = Vertex(self.mesh, 4) vertex_5 = Vertex(self.mesh, 5) editor.add_cell(0,1,2,3) editor.add_cell(1,0,2,3) editor.close()
def test_readme_images(): from dolfin import ( MeshEditor, Mesh, FunctionSpace, assemble, EigenMatrix, dot, grad, dx, TrialFunction, TestFunction ) import meshzoo points, cells = meshzoo.rectangle(-1.0, 1.0, -1.0, 1.0, 20, 20) # Convert points, cells to dolfin mesh editor = MeshEditor() mesh = Mesh() # topological and geometrical dimension 2 editor.open(mesh, 'triangle', 2, 2, 1) editor.init_vertices(len(points)) editor.init_cells(len(cells)) for k, point in enumerate(points): editor.add_vertex(k, point[:2]) for k, cell in enumerate(cells.astype(numpy.uintp)): editor.add_cell(k, cell) editor.close() V = FunctionSpace(mesh, 'CG', 1) u = TrialFunction(V) v = TestFunction(V) L = EigenMatrix() assemble(dot(grad(u), grad(v)) * dx, tensor=L) A = L.sparray() # M = A.T.dot(A) M = A with tempfile.TemporaryDirectory() as temp_dir: filepath = os.path.join(temp_dir, 'test.png') betterspy.write_png(filepath, M, border_width=2) # betterspy.write_png( # 'ATA.png', M, border_width=2, # colormap='viridis' # ) return
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 get(self): """One triangle per side in smaller, two triangles in larger.""" sides, R = self.pad(self.values) mesh = Mesh() large = [np.array((cos(2 * pi * i / sides), sin(2 * pi * i / sides))) for i in range(1, sides+1)] small = np.array([v * R for v in large]) # centers of edges in large polygon center = np.array([(v + w) / 2 for v, w in zip(large, large[1:] + [large[0]])]) large = np.array(large) editor = MeshEditor() editor.open(mesh, 2, 2) editor.init_vertices(3 * sides) editor.init_cells(3 * sides) for i in range(sides): editor.add_vertex(3 * i, *large[i]) editor.add_vertex(3 * i + 1, *small[i]) editor.add_vertex(3 * i + 2, *center[i]) for i, j in zip(range(sides), range(1, sides) + [0]): editor.add_cell(3*i, 3*i, 3*i+1, 3*i+2) editor.add_cell(3*i+1, 3*i+1, 3*i+2, 3*j+1) editor.add_cell(3*i+2, 3*i+2, 3*j+1, 3*j) editor.close() return mesh
def get(self): """One triangle per side in smaller, two triangles in larger.""" sides, R = self.pad(self.values) mesh = Mesh() large = [ np.array((cos(2 * pi * i / sides), sin(2 * pi * i / sides))) for i in range(1, sides + 1) ] small = np.array([v * R for v in large]) # centers of edges in large polygon center = np.array([(v + w) / 2 for v, w in zip(large, large[1:] + [large[0]])]) large = np.array(large) editor = MeshEditor() editor.open(mesh, 2, 2) editor.init_vertices(3 * sides) editor.init_cells(3 * sides) for i in range(sides): editor.add_vertex(3 * i, *large[i]) editor.add_vertex(3 * i + 1, *small[i]) editor.add_vertex(3 * i + 2, *center[i]) for i, j in zip(range(sides), range(1, sides) + [0]): editor.add_cell(3 * i, 3 * i, 3 * i + 1, 3 * i + 2) editor.add_cell(3 * i + 1, 3 * i + 1, 3 * i + 2, 3 * j + 1) editor.add_cell(3 * i + 2, 3 * i + 2, 3 * j + 1, 3 * j) editor.close() return mesh
def make_mesh(vertices, cells, cell_type): '''Mesh from data by MeshEditor''' gdim = cell_type.geometric_dimension() assert vertices.shape[1] == gdim tdim = cell_type.topological_dimension() mesh = Mesh() editor = MeshEditor() editor.open(mesh, str(cell_type), tdim, gdim) editor.init_vertices(len(vertices)) editor.init_cells(len(cells)) for vi, x in enumerate(vertices): editor.add_vertex(vi, x) for ci, c in enumerate(cells): editor.add_cell(ci, *c) editor.close() return mesh
def get(self): """Build vertices from polar coordinates.""" angle, dist = self.values if len(angle) < 3: angle = np.array(range(int(angle[0]))) * 360.0 / angle[0] while len(dist) < len(angle): dist = dist * 2 dist = np.array(dist) sides = len(angle) mesh = Mesh() editor = MeshEditor() editor.open(mesh, 2, 2) editor.init_vertices(sides + 1) editor.init_cells(sides) editor.add_vertex(0, 0, 0) for i in range(1, sides + 1): editor.add_vertex(i, dist[i - 1] * cos(angle[i - 1] / 180.0 * pi), dist[i - 1] * sin(angle[i - 1] / 180.0 * pi)) for i in range(sides - 1): editor.add_cell(i, 0, i + 1, i + 2) editor.add_cell(sides - 1, 0, sides, 1) editor.close() return mesh
def barycentric_refine(mesh): from dolfin import Mesh, MeshEditor # the extension to 3d is straightforward but not yet implemented assert mesh.topology().dim() is 2 # barycentric refinement v = mesh.coordinates() t = mesh.cells() b = (v[t[:,0],:]+v[t[:,1],:]+v[t[:,2],:])/3 mesh = Mesh() editor = MeshEditor() editor.open(mesh, 2, 2); # add vertices to mesh nv0 = len(v) nv1 = nv0 + len(t) editor.init_vertices(nv1) for i, vi in enumerate(v): editor.add_vertex(i, vi[0], vi[1]) for i, vi in enumerate(b): editor.add_vertex(i + nv0, vi[0], vi[1]) # add cells to the mesh nt1 = 3*len(t) editor.init_cells(nt1) for i, ti in enumerate(t): editor.add_cell(i*3+0, ti[0], ti[1], nv0 + i) editor.add_cell(i*3+1, ti[1], ti[2], nv0 + i) editor.add_cell(i*3+2, ti[2], ti[0], nv0 + i) # done: create and return mesh object editor.close() return mesh
def reduced_mesh(mesh): ''' Represent each branch only as a segment / single cell in the mesh. The mesh has a map from new mesh to old mesh vertices ''' terminals, _ = find_branches(mesh) # Unique nodes, this is map from rmesh nodes to parent nodes = map(int, set(sum(terminals, ()))) # Let's make reverse for purpose of creating the mesh old2new = {old: new for new, old in enumerate(nodes)} # Their coordinates x = mesh.coordinates()[nodes] rmesh = Mesh() editor = MeshEditor() editor.open(rmesh, 1, mesh.geometry().dim()) editor.init_vertices(len(x)) editor.init_cells(len(terminals)) # Add vertices for vi, v in enumerate(x): editor.add_vertex(vi, v) # Add cells for ci, c in enumerate(terminals): editor.add_cell(ci, *map(lambda v: old2new[v], c)) editor.close() # How to do this with MeshData rmesh.parent_vertex_indices = nodes return rmesh
def get(self): """Eight cells.""" mesh = Mesh() editor = MeshEditor() editor.open(mesh, 3, 3) editor.init_vertices(7) editor.init_cells(8) editor.add_vertex(0, 1, 0, 0) editor.add_vertex(1, 0, 1, 0) editor.add_vertex(2, 0, 0, 1) editor.add_vertex(3, -1, 0, 0) editor.add_vertex(4, 0, -1, 0) editor.add_vertex(5, 0, 0, -1) editor.add_vertex(6, 0, 0, 0) editor.add_cell(0, 6, 0, 1, 2) editor.add_cell(1, 6, 0, 1, 5) editor.add_cell(2, 6, 0, 4, 2) editor.add_cell(3, 6, 0, 4, 5) editor.add_cell(4, 6, 3, 1, 2) editor.add_cell(5, 6, 3, 1, 5) editor.add_cell(6, 6, 3, 4, 2) editor.add_cell(7, 6, 3, 4, 5) editor.close() return mesh
def gmsh2xml(ifilename, handler): """Convert between .gmsh v2.0 format (http://www.geuz.org/gmsh/) and .xml, parser implemented as a state machine: 0 = read 'MeshFormat' 1 = read mesh format data 2 = read 'EndMeshFormat' 3 = read 'Nodes' 4 = read number of vertices 5 = read vertices 6 = read 'EndNodes' 7 = read 'Elements' 8 = read number of cells 9 = read cells 10 = done Afterwards, extract physical region numbers if they are defined in the mesh file as a mesh function. """ print "Converting from Gmsh format (.msh, .gmsh) to DOLFIN XML format" # The dimension of the gmsh element types supported here as well as the dolfin cell types for each dimension gmsh_dim = {15: 0, 1: 1, 2: 2, 4: 3} cell_type_for_dim = {1: "interval", 2: "triangle", 3: "tetrahedron" } # the gmsh element types supported for conversion supported_gmsh_element_types = [1, 2, 4, 15] # Open files ifile = open(ifilename, "r") # Scan file for cell type cell_type = None highest_dim = 0 line = ifile.readline() while line: # Remove newline if line[-1] == "\n": line = line[:-1] # Read dimension if line.find("$Elements") == 0: line = ifile.readline() num_elements = int(line) if num_elements == 0: _error("No elements found in gmsh file.") line = ifile.readline() # Now iterate through elements to find largest dimension. Gmsh # format might include elements of lower dimensions in the element list. # We also need to count number of elements of correct dimensions. # Also determine which vertices are not used. dim_count = {0: 0, 1: 0, 2: 0, 3: 0} vertices_used_for_dim = {0: [], 1: [], 2: [], 3: []} # Array used to store gmsh tags for 1D (type 1/line), 2D (type 2/triangular) elements and 3D (type 4/tet) elements tags_for_dim = {0: [], 1: [], 2: [], 3: []} while line.find("$EndElements") == -1: element = line.split() elem_type = int(element[1]) num_tags = int(element[2]) if elem_type in supported_gmsh_element_types: dim = gmsh_dim[elem_type] if highest_dim < dim: highest_dim = dim node_num_list = [int(node) for node in element[3 + num_tags:]] vertices_used_for_dim[dim].extend(node_num_list) if num_tags > 0: tags_for_dim[dim].append(tuple(int(tag) for tag in element[3:3+num_tags])) dim_count[dim] += 1 else: #TODO: output a warning here. "gmsh element type %d not supported" % elem_type pass line = ifile.readline() else: # Read next line line = ifile.readline() # Check that we got the cell type and set num_cells_counted if highest_dim == 0: _error("Unable to find cells of supported type.") num_cells_counted = dim_count[highest_dim] vertex_set = set(vertices_used_for_dim[highest_dim]) vertices_used_for_dim[highest_dim] = None vertex_dict = {} for n,v in enumerate(vertex_set): vertex_dict[v] = n # Step to beginning of file ifile.seek(0) # Set mesh type handler.set_mesh_type(cell_type_for_dim[highest_dim], highest_dim) # Initialise node list (gmsh does not export all vertexes in order) nodelist = {} # Current state state = 0 # Write data num_vertices_read = 0 num_cells_read = 0 # Only import the dolfin objects if facet markings exist process_facets = False if len(tags_for_dim[highest_dim-1]) > 0: # first construct the mesh try: from dolfin import MeshEditor, Mesh except ImportError: _error("DOLFIN must be installed to handle Gmsh boundary regions") mesh = Mesh() mesh_editor = MeshEditor () mesh_editor.open( mesh, highest_dim, highest_dim ) process_facets = True else: # TODO: Output a warning or an error here me = None while state != 10: # Read next line line = ifile.readline() if not line: break # Skip comments if line[0] == '#': continue # Remove newline if line[-1] == "\n": line = line[:-1] if state == 0: if line == "$MeshFormat": state = 1 elif state == 1: (version, file_type, data_size) = line.split() state = 2 elif state == 2: if line == "$EndMeshFormat": state = 3 elif state == 3: if line == "$Nodes": state = 4 elif state == 4: num_vertices = len(vertex_dict) handler.start_vertices(num_vertices) if process_facets: mesh_editor.init_vertices ( num_vertices ) state = 5 elif state == 5: (node_no, x, y, z) = line.split() node_no = int(node_no) x,y,z = [float(xx) for xx in (x,y,z)] if vertex_dict.has_key(node_no): node_no = vertex_dict[node_no] else: continue nodelist[int(node_no)] = num_vertices_read handler.add_vertex(num_vertices_read, [x, y, z]) if process_facets: if highest_dim == 1: coords = numpy.array([x]) elif highest_dim == 2: coords = numpy.array([x, y]) elif highest_dim == 3: coords = numpy.array([x, y, z]) mesh_editor.add_vertex(num_vertices_read, coords) num_vertices_read +=1 if num_vertices == num_vertices_read: handler.end_vertices() state = 6 elif state == 6: if line == "$EndNodes": state = 7 elif state == 7: if line == "$Elements": state = 8 elif state == 8: handler.start_cells(num_cells_counted) if process_facets: mesh_editor.init_cells( num_cells_counted ) state = 9 elif state == 9: element = line.split() elem_type = int(element[1]) num_tags = int(element[2]) if elem_type in supported_gmsh_element_types: dim = gmsh_dim[elem_type] else: dim = 0 if dim == highest_dim: node_num_list = [vertex_dict[int(node)] for node in element[3 + num_tags:]] for node in node_num_list: if not node in nodelist: _error("Vertex %d of %s %d not previously defined." % (node, cell_type_for_dim[dim], num_cells_read)) cell_nodes = [nodelist[n] for n in node_num_list] handler.add_cell(num_cells_read, cell_nodes) if process_facets: cell_nodes = numpy.array([nodelist[n] for n in node_num_list], dtype=numpy.uintp) mesh_editor.add_cell(num_cells_read, cell_nodes) num_cells_read +=1 if num_cells_counted == num_cells_read: handler.end_cells() if process_facets: mesh_editor.close() state = 10 elif state == 10: break # Write mesh function based on the Physical Regions defined by # gmsh, but only if they are not all zero. All zero physical # regions indicate that no physical regions were defined. if highest_dim not in [1,2,3]: _error("Gmsh tags not supported for dimension %i. Probably a bug" % dim) tags = tags_for_dim[highest_dim] physical_regions = tuple(tag[0] for tag in tags) if not all(tag == 0 for tag in physical_regions): handler.start_meshfunction("physical_region", dim, num_cells_counted) for i, physical_region in enumerate(physical_regions): handler.add_entity_meshfunction(i, physical_region) handler.end_meshfunction() # Now process the facet markers tags = tags_for_dim[highest_dim-1] if (len(tags) > 0) and (mesh is not None): physical_regions = tuple(tag[0] for tag in tags) if not all(tag == 0 for tag in physical_regions): mesh.init(highest_dim-1,0) # Get the facet-node connectivity information (reshape as a row of node indices per facet) if highest_dim==1: # for 1d meshes the mesh topology returns the vertex to vertex map, which isn't what we want # as facets are vertices facets_as_nodes = numpy.array([[i] for i in range(mesh.num_facets())]) else: facets_as_nodes = mesh.topology()(highest_dim-1,0)().reshape ( mesh.num_facets(), highest_dim ) # Build the reverse map nodes_as_facets = {} for facet in range(mesh.num_facets()): nodes_as_facets[tuple(facets_as_nodes[facet,:])] = facet data = [int(0*k) for k in range(mesh.num_facets()) ] for i, physical_region in enumerate(physical_regions): nodes = [n-1 for n in vertices_used_for_dim[highest_dim-1][highest_dim*i:(highest_dim*i+highest_dim)]] nodes.sort() if physical_region != 0: try: index = nodes_as_facets[tuple(nodes)] data[index] = physical_region except IndexError: raise Exception ( "The facet (%d) was not found to mark: %s" % (i, nodes) ) # # Create and initialise the mesh function handler.start_meshfunction("facet_region", highest_dim-1, mesh.num_facets() ) for index, physical_region in enumerate ( data ): handler.add_entity_meshfunction(index, physical_region) handler.end_meshfunction() # Check that we got all data if state == 10: print "Conversion done" else: _error("Missing data, unable to convert \n\ Did you use version 2.0 of the gmsh file format?") # Close files ifile.close()
def gmsh_to_dolfin_mesh(ifilename, handler): """Convert between .gmsh v2.0 format (http://www.geuz.org/gmsh/) and .xml, parser implemented as a state machine: 0 = read 'MeshFormat' 1 = read mesh format data 2 = read 'EndMeshFormat' 3 = read 'Nodes' 4 = read number of vertices 5 = read vertices 6 = read 'EndNodes' 7 = read 'Elements' 8 = read number of cells 9 = read cells 10 = done Afterwards, extract physical region numbers if they are defined in the mesh file as a mesh function. """ print "Converting from Gmsh format (.msh, .gmsh) to DOLFIN XML format" # The dimension of the gmsh element types supported here as well as the dolfin cell types for each dimension gmsh_dim = {1: 1, 2: 2, 4: 3} gmsh_cell_type = {1: "interval", 2: "triangle", 3: "tetrahedron"} # the gmsh element types supported for conversion supported_gmsh_element_types = [1, 2, 4] # Open files ifile = open(ifilename, "r") # Scan file for cell type cell_type = None highest_dim = 0 line = ifile.readline() while line: # Remove newline if line[-1] == "\n": line = line[:-1] # Read dimension if line.find("$Elements") == 0: line = ifile.readline() num_elements = int(line) num_cells_counted = 0 if num_elements == 0: _error("No elements found in gmsh file.") line = ifile.readline() # Now iterate through elements to find largest dimension. Gmsh # format might include elements of lower dimensions in the element list. # We also need to count number of elements of correct dimensions. # Also determine which vertices are not used. dim_count = {1: 0, 2: 0, 3: 0} vertices_used = {1: [], 2: [], 3: []} # Array used to store gmsh tags for 1D (type 1/line), 2D (type 2/triangular) elements and 3D (type 4/tet) elements tags_for_dim = {1: [], 2: [], 3: []} while line.find("$EndElements") == -1: element = line.split() elem_type = int(element[1]) num_tags = int(element[2]) if elem_type in supported_gmsh_element_types: dim = gmsh_dim[elem_type] if highest_dim < dim: highest_dim = dim node_num_list = [ int(node) for node in element[3 + num_tags:] ] vertices_used[dim].extend(node_num_list) if num_tags > 0: tags_for_dim[dim].append( tuple(int(tag) for tag in element[3:3 + num_tags])) dim_count[dim] += 1 else: #TODO: output a warning here. "gmsh element type %d not supported" % elem_type pass line = ifile.readline() else: # Read next line line = ifile.readline() # Check that we got the cell type and set num_cells_counted if highest_dim == 0: _error("Unable to find cells of supported type.") num_cells_counted = dim_count[highest_dim] vertex_set = set(vertices_used[highest_dim]) vertices_used[highest_dim] = None vertex_dict = {} for n, v in enumerate(vertex_set): vertex_dict[v] = n # Step to beginning of file ifile.seek(0) # Set mesh type handler.set_mesh_type(gmsh_cell_type[highest_dim], highest_dim) # Initialise node list (gmsh does not export all vertexes in order) nodelist = {} # Current state state = 0 # Write data num_vertices_read = 0 num_cells_read = 0 # Now handle the facet markings if len(tags_for_dim[highest_dim - 1]) > 0: # first construct the mesh from dolfin import MeshEditor, Mesh mesh = Mesh() me = MeshEditor() me.open(mesh, highest_dim, highest_dim) else: me = None while state != 10: # Read next line line = ifile.readline() if not line: break # Skip comments if line[0] == '#': continue # Remove newline if line[-1] == "\n": line = line[:-1] if state == 0: if line == "$MeshFormat": state = 1 elif state == 1: (version, file_type, data_size) = line.split() state = 2 elif state == 2: if line == "$EndMeshFormat": state = 3 elif state == 3: if line == "$Nodes": state = 4 elif state == 4: num_vertices = len(vertex_dict) handler.start_vertices(num_vertices) if me is not None: me.init_vertices(num_vertices) state = 5 elif state == 5: (node_no, x, y, z) = line.split() node_no = int(node_no) x, y, z = [float(xx) for xx in (x, y, z)] if vertex_dict.has_key(node_no): node_no = vertex_dict[node_no] else: continue nodelist[int(node_no)] = num_vertices_read handler.add_vertex(num_vertices_read, [x, y, z]) if me is not None: if highest_dim == 1: me.add_vertex(num_vertices_read, x) elif highest_dim == 2: me.add_vertex(num_vertices_read, x, y) elif highest_dim == 3: me.add_vertex(num_vertices_read, x, y, z) num_vertices_read += 1 if num_vertices == num_vertices_read: handler.end_vertices() state = 6 elif state == 6: if line == "$EndNodes": state = 7 elif state == 7: if line == "$Elements": state = 8 elif state == 8: handler.start_cells(num_cells_counted) if me is not None: me.init_cells(num_cells_counted) state = 9 elif state == 9: element = line.split() elem_type = int(element[1]) num_tags = int(element[2]) if elem_type in supported_gmsh_element_types: dim = gmsh_dim[elem_type] else: dim = 0 if dim == highest_dim: node_num_list = [ vertex_dict[int(node)] for node in element[3 + num_tags:] ] for node in node_num_list: if not node in nodelist: _error("Vertex %d of %s %d not previously defined." % (node, gmsh_cell_type[dim], num_cells_read)) cell_nodes = [nodelist[n] for n in node_num_list] handler.add_cell(num_cells_read, cell_nodes) if me is not None: me.add_cell(num_cells_read, *cell_nodes) num_cells_read += 1 if num_cells_counted == num_cells_read: handler.end_cells() if me is not None: me.close() state = 10 elif state == 10: break # Write mesh function based on the Physical Regions defined by # gmsh, but only if they are not all zero. All zero physical # regions indicate that no physical regions were defined. if highest_dim not in [1, 2, 3]: _error("Gmsh tags not supported for dimension %i. Probably a bug" % dim) tags = tags_for_dim[highest_dim] physical_regions = tuple(tag[0] for tag in tags) if not all(tag == 0 for tag in physical_regions): handler.start_meshfunction("physical_region", dim, num_cells_counted) for i, physical_region in enumerate(physical_regions): handler.add_entity_meshfunction(i, physical_region) handler.end_meshfunction() # Now process the facet markers tags = tags_for_dim[highest_dim - 1] if len(tags) > 0: print tags print vertices_used[highest_dim - 1] physical_regions = tuple(tag[0] for tag in tags) if not all(tag == 0 for tag in physical_regions): mesh.init(highest_dim - 1, 0) # Get the facet-node connectivity information (reshape as a row of node indices per facet) facets_as_nodes = mesh.topology()(highest_dim - 1, 0)().reshape( mesh.num_facets(), highest_dim) # from dolfin import MeshFunction # # Create and initialise the mesh function # facet_mark_function = MeshFunction ( 'uint', mesh, highest_dim-1 ) # facet_mark_function.set_all( 0 ) handler.start_meshfunction("facet_region", highest_dim - 1, mesh.num_facets()) facets_to_check = range(mesh.num_facets()) data = [int(0 * k) for k in range(len(facets_to_check))] for i, physical_region in enumerate(physical_regions): nodes = [ n - 1 for n in vertices_used[highest_dim - 1][2 * i:(2 * i + highest_dim)] ] nodes.sort() if physical_region != 0: found = False for j in range(len(facets_to_check)): index = facets_to_check[j] if all(facets_as_nodes[index, k] == nodes[k] for k in range(len(nodes))): found = True facets_to_check.pop(j) # set the value of the mesh function # facet_mark_function[index] = physical_region data[index] = physical_region break if not found: raise Exception( "The facet (%d) was not found to mark: %s" % (i, nodes)) # fname = os.path.splitext('tmp.xml')[0] # mesh_function_file = File("%s_%s.xml" % (fname, "facet_region")) # mesh_function_file << facet_mark_function for index, physical_region in enumerate(data): handler.add_entity_meshfunction(index, physical_region) handler.end_meshfunction() mf = MeshFunction('uint', mesh, 'tmp_facet_region.xml') plot(mf, interactive=True) # Check that we got all data if state == 10: print "Conversion done" else: _error( "Missing data, unable to convert \n\ Did you use version 2.0 of the gmsh file format?" ) # Close files ifile.close()
def _main(): args = _parse_cmd_arguments() content = np.load(args.infile) data = content.item()["data"] n = content.item()["n"] # # plot statistics # axes0 = problem.get_ellipse_axes(alpha0).T.flatten() # plt.plot(axes0, label='axes lengths before') # axes1 = problem.get_ellipse_axes(out.x).T.flatten() # plt.plot(axes1, label='axes lengths opt') # plt.legend() # plt.grid() # Plot unperturbed MacAdam # colorio.plot_luo_rigg( # ellipse_scaling=1, colorio.save_macadam("macadam-native.png", ellipse_scaling=10, plot_rgb_triangle=False, n=n) points, cells = meshzoo.triangle(corners=np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]), n=n) # https://bitbucket.org/fenics-project/dolfin/issues/845/initialize-mesh-from-vertices editor = MeshEditor() mesh = Mesh() editor.open(mesh, "triangle", 2, 2) editor.init_vertices(points.shape[0]) editor.init_cells(cells.shape[0]) for k, point in enumerate(points): editor.add_vertex(k, point[:2]) for k, cell in enumerate(cells): editor.add_cell(k, cell) editor.close() V = FunctionSpace(mesh, "CG", 1) def get_u(alpha): n = V.dim() ax = alpha[:n] ay = alpha[n:] ux = Function(V) ux.vector().set_local(ax) ux.vector().apply("") uy = Function(V) uy.vector().set_local(ay) uy.vector().apply("") return ux, uy # Plot perturbed MacAdam def transform(XY, data=data): is_solo = len(XY.shape) == 1 if is_solo: XY = np.array([XY]).T # print(XY) ux, uy = get_u(data) out = np.array([[ux(x, y) for x, y in XY.T], [uy(x, y) for x, y in XY.T]]) if is_solo: out = out[..., 0] return out # colorio.plot_luo_rigg( # ellipse_scaling=1, plt.figure() colorio.plot_macadam( ellipse_scaling=10, # xy_to_2d=problem.pade2d.eval, xy_to_2d=transform, plot_rgb_triangle=False, mesh_resolution=n, ) # plt.xlim(-0.2, 0.9) # plt.ylim(+0.0, 0.7) plt.savefig(f"macadam-{n:03d}.png") return
def create_submesh(mesh, markers, marker): "This function allows for a SubMesh-equivalent to be created in parallel" # Build mesh submesh = Mesh() mesh_editor = MeshEditor() mesh_editor.open(submesh, mesh.ufl_cell().cellname(), mesh.ufl_cell().topological_dimension(), mesh.ufl_cell().geometric_dimension()) # Return empty mesh if no matching markers if MPI.sum(mpi_comm_world(), int(marker in markers.array())) == 0: cbc_warning( "Unable to find matching markers in meshfunction. Submesh is empty." ) mesh_editor.close() return submesh base_cell_indices = np.where(markers.array() == marker)[0] base_cells = mesh.cells()[base_cell_indices] base_vertex_indices = np.unique(base_cells.flatten()) base_global_vertex_indices = sorted( [mesh.topology().global_indices(0)[vi] for vi in base_vertex_indices]) gi = mesh.topology().global_indices(0) shared_local_indices = set(base_vertex_indices).intersection( set(mesh.topology().shared_entities(0).keys())) shared_global_indices = [gi[vi] for vi in shared_local_indices] unshared_global_indices = list( set(base_global_vertex_indices) - set(shared_global_indices)) unshared_vertices_dist = distribution(len(unshared_global_indices)) # Number unshared vertices on separate process idx = sum(unshared_vertices_dist[:MPI.rank(mpi_comm_world())]) base_to_sub_global_indices = {} for gi in unshared_global_indices: base_to_sub_global_indices[gi] = idx idx += 1 # Gather all shared process on process 0 and assign global index all_shared_global_indices = gather(shared_global_indices, on_process=0, flatten=True) all_shared_global_indices = np.unique(all_shared_global_indices) shared_base_to_sub_global_indices = {} idx = int( MPI.max(mpi_comm_world(), float(max(base_to_sub_global_indices.values() + [-1e16]))) + 1) if MPI.rank(mpi_comm_world()) == 0: for gi in all_shared_global_indices: shared_base_to_sub_global_indices[int(gi)] = idx idx += 1 # Broadcast global numbering of all shared vertices shared_base_to_sub_global_indices = dict( zip(broadcast(shared_base_to_sub_global_indices.keys(), 0), broadcast(shared_base_to_sub_global_indices.values(), 0))) # Join shared and unshared numbering in one dict base_to_sub_global_indices = dict( base_to_sub_global_indices.items() + shared_base_to_sub_global_indices.items()) # Create mapping of local indices base_to_sub_local_indices = dict( zip(base_vertex_indices, range(len(base_vertex_indices)))) # Define sub-cells sub_cells = [None] * len(base_cells) for i, c in enumerate(base_cells): sub_cells[i] = [base_to_sub_local_indices[j] for j in c] # Store vertices as sub_vertices[local_index] = (global_index, coordinates) sub_vertices = {} for base_local, sub_local in base_to_sub_local_indices.items(): sub_vertices[sub_local] = (base_to_sub_global_indices[ mesh.topology().global_indices(0)[base_local]], mesh.coordinates()[base_local]) ## Done with base mesh # Distribute meshdata on (if any) empty processes sub_cells, sub_vertices = distribute_meshdata(sub_cells, sub_vertices) global_cell_distribution = distribution(len(sub_cells)) #global_vertex_distribution = distribution(len(sub_vertices)) global_num_cells = MPI.sum(mpi_comm_world(), len(sub_cells)) global_num_vertices = sum(unshared_vertices_dist) + MPI.sum( mpi_comm_world(), len(all_shared_global_indices)) mesh_editor.init_vertices(len(sub_vertices)) #mesh_editor.init_cells(len(sub_cells)) mesh_editor.init_cells_global(len(sub_cells), global_num_cells) global_index_start = sum( global_cell_distribution[:MPI.rank(mesh.mpi_comm())]) for index, cell in enumerate(sub_cells): if LooseVersion(dolfin_version()) >= LooseVersion("1.6.0"): mesh_editor.add_cell(index, *cell) else: mesh_editor.add_cell(int(index), global_index_start + index, np.array(cell, dtype=np.uintp)) for local_index, (global_index, coordinates) in sub_vertices.items(): #print coordinates mesh_editor.add_vertex_global(int(local_index), int(global_index), coordinates) mesh_editor.close() submesh.topology().init(0, len(sub_vertices), global_num_vertices) submesh.topology().init(mesh.ufl_cell().topological_dimension(), len(sub_cells), global_num_cells) # FIXME: Set up shared entities # What damage does this do? submesh.topology().shared_entities(0)[0] = [] # The code below sets up shared vertices, but lacks shared facets. # It is considered incomplete, and therefore commented out ''' #submesh.topology().shared_entities(0)[0] = [] from dolfin import compile_extension_module cpp_code = """ void set_shared_entities(Mesh& mesh, std::size_t idx, const Array<std::size_t>& other_processes) { std::set<unsigned int> set_other_processes; for (std::size_t i=0; i<other_processes.size(); i++) { set_other_processes.insert(other_processes[i]); //std::cout << idx << " --> " << other_processes[i] << std::endl; } //std::cout << idx << " --> " << set_other_processes[0] << std::endl; mesh.topology().shared_entities(0)[idx] = set_other_processes; } """ set_shared_entities = compile_extension_module(cpp_code).set_shared_entities base_se = mesh.topology().shared_entities(0) se = submesh.topology().shared_entities(0) for li in shared_local_indices: arr = np.array(base_se[li], dtype=np.uintp) sub_li = base_to_sub_local_indices[li] set_shared_entities(submesh, base_to_sub_local_indices[li], arr) ''' return submesh
def convert(ifilename, handler): """ Convert from Abaqus. The Abaqus format first defines a node block, then there should be a number of elements containing these nodes. """ # Dictionary of nodes (maps node id to coordinates) nodes = {} # Dictionary of elements (maps cell id to list of cell nodes) elems = {} # Lists of nodes for given name (key) node_sets = {} # Lists of cells for given name (key) cell_sets = {} # Lists of surfaces for given name (key) in the format: # {'SS1': [set(['SS1_S1', 'S1']), set(['SS1_S4', 'S4'])]}, # where SS1 is the name of the surface, SS1_S1 is the name of the # cell list whose first face is to be selected, ... surface_sets = {} # Open file Abaqus file csv_file = csv.reader(open(ifilename, 'rb'), delimiter=',', skipinitialspace=True) node_set_name = None generate = None # Set intial state state state = State.Init # Read data from input file for l in csv_file: # Sanity check if (len(l) == 0): print "Ooops, zero length." if l[0].startswith('**'): # Pass over comments continue elif l[0].startswith('*'): # Have a keyword state = State.Unknown if l[0].lower() == "*heading": state = State.ReadHeading elif l[0].lower() == "*part": part_name = _read_part_name(l) elif l[0].lower() == "*end part": state = State.Invalid elif l[0].lower() == "*node": node_set_name = _create_node_list_entry(node_sets, l) state = State.ReadNodes elif l[0].lower() == "*element": cell_type, cell_set_name = _read_element_keywords(cell_sets, l) state = State.ReadCells elif l[0].lower() == "*nset": node_set_name, generate = _read_nset_keywords(node_sets, l) state = State.ReadNodeSet elif l[0].lower() == "*elset": cell_set_name, generate = _read_elset_keywords(cell_sets, l) if generate: print "WARNING: generation of *elsets not tested." state = State.ReadCellSet elif l[0].lower() == "*surface": surface_set_name, generate = _read_surface_keywords(surface_sets, l) state = State.ReadSurfaceSet else: print "WARNING: unrecognised Abaqus input keyword:", l[0] state = State.Unknown else: if state == State.ReadHeading: model_name = _read_heading(l) elif state == State.ReadNodes: node_id = int(l[0]) - 1 coords = [float(c) for c in l[1:]] nodes[node_id] = coords if node_set_name is not None: node_sets[node_set_name].add(node_id) elif state == State.ReadCells: cell_id = int(l[0]) - 1 cell_connectivity = [int(v) - 1 for v in l[1:]] elems[cell_id] = cell_connectivity if cell_set_name is not None: cell_sets[cell_set_name].add(cell_id) elif state == State.ReadNodeSet: try: if generate: n0, n1, increment = l node_range = range(int(n0) - 1, int(n1) - 1, int(increment)) node_range.append(int(n1) - 1) node_sets[node_set_name].update(node_range) else: # Strip empty term at end of list, if present if l[-1] == '': l.pop(-1) node_range = [int(n) - 1 for n in l] node_sets[node_set_name].update(node_range) except: print "WARNING: Non-integer node sets not yet supported." elif state == State.ReadCellSet: try: if generate: n0, n1, increment = l cell_range = range(int(n0) - 1, int(n1) - 1, int(increment)) cell_range.append(int(n1) - 1) cell_sets[cell_set_name].update(cell_range) else: # Strip empty term at end of list, if present if l[-1] == '': l.pop(-1) cell_range = [int(n) - 1 for n in l] cell_sets[cell_set_name].update(cell_range) except: print "WARNING: Non-integer element sets not yet supported." elif state == State.ReadSurfaceSet: # Strip empty term at end of list, if present if l[-1] == '': l.pop(-1) surface_sets[surface_set_name].update([tuple(l)]) elif state == State.Invalid: # part raise StandardError("Inavlid Abaqus parser state..") # Close CSV object del csv_file # Write data to XML file # Note that vertices/cells must be consecutively numbered, which # isn't necessarily the case in Abaqus. Therefore we enumerate and # translate original IDs to sequence indexes if gaps are present. # FIXME handler.set_mesh_type("tetrahedron", 3) process_facets = len(surface_sets) > 0 if process_facets: try: from dolfin import MeshEditor, Mesh except ImportError: _error("DOLFIN must be installed to handle Abaqus boundary regions") mesh = Mesh() mesh_editor = MeshEditor() mesh_editor.open(mesh, 3, 3) node_ids_order = {} # Check for gaps in vertex numbering node_ids = nodes.keys() if len(node_ids) > 0: vertex_gap = (min(node_ids) != 0 or max(node_ids) != len(node_ids) - 1) for x, y in enumerate(node_ids): node_ids_order[y]= x # Maps Abaqus IDs to Dolfin IDs else: vertex_gap = True # Check for gaps in cell numbering elemids = elems.keys() if len(elemids) > 0: cell_gap = (min(elemids) != 0 or max(elemids) != len(elemids) - 1) else: cell_gap = True # Write vertices to XML file handler.start_vertices(len(nodes)) if process_facets: mesh_editor.init_vertices (len(nodes)) if not vertex_gap: for v_id, v_coords in nodes.items(): handler.add_vertex(v_id, v_coords) if process_facets: mesh_editor.add_vertex(v_id, np.array(v_coords, dtype=np.float_)) else: for idx, (v_id, v_coords) in enumerate(nodes.items()): handler.add_vertex(idx, v_coords) if process_facets: mesh_editor.add_vertex(idx, np.array(v_coords, dtype=np.float_)) handler.end_vertices() # Write cells to XML file handler.start_cells(len(elems)) if process_facets: mesh_editor.init_cells(len(elems)) if not vertex_gap and not cell_gap: for c_index, c_data in elems.items(): for v_id in c_data: if not (0 <= v_id < len(nodes)): handler.error("Element %s references non-existent node %s" % (c_index, v_id)) handler.add_cell(c_index, c_data) if process_facets: c_data_tmp = np.array(c_data) c_data_tmp.sort() mesh_editor.add_cell(c_index, np.array(c_data_tmp, dtype=np.uintp)) elif not vertex_gap and cell_gap: for idx, (c_index, c_data) in enumerate(elems.items()): for v_id in c_data: if not (0 <= v_id < len(nodes)): handler.error("Element %s references non-existent node %s" % (c_index, v_id)) handler.add_cell(idx, c_data) if process_facets: c_data_tmp = np.array(c_data) c_data_tmp.sort() mesh_editor.add_cell(idx, np.array(c_data_tmp, dtype=np.uintp)) else: for idx, (c_id, c_data) in enumerate(elems.items()): c_nodes = [] for v_id in c_data: try: c_nodes.append(node_ids_order[v_id]) except ValueError: handler.error("Element %s references non-existent node %s" % (c_id, v_id)) handler.add_cell(idx, c_nodes) if process_facets: c_nodes.sort() mesh_editor.add_cell(idx, np.array(c_nodes, dtype=np.uintp)) handler.end_cells() # Write MeshValueCollections to XML file handler.start_domains() # Build a abaqus node ID -> dolfin cell ID map (which is not unique but that is irrelevant here) # and its local entity. if len(node_sets.items()) > 0: node_cell_map = {} for c_dolfin_index, (c_index, c_data) in enumerate(elems.items()): c_data_tmp = np.array(c_data) c_data_tmp.sort() for local_entity, n_index in enumerate(c_data_tmp): node_cell_map[n_index] = (c_dolfin_index, local_entity) # Write vertex/node sets dim = 0 for value, (name, node_set) in enumerate(node_sets.items()): handler.start_mesh_value_collection(name, dim, len(node_set), "uint") for node in node_set: try: cell, local_entity = node_cell_map[node] handler.add_entity_mesh_value_collection(dim, cell, value, local_entity=local_entity) except KeyError: print "Warning: Boundary references non-existent node %s" % node handler.end_mesh_value_collection() # Write cell/element sets dim = 3 for name, s in cell_sets.items(): handler.start_mesh_value_collection(name, dim, len(s), "uint") for cell in s: handler.add_entity_mesh_value_collection(dim, cell, 0) handler.end_mesh_value_collection() # Write surface sets if process_facets: dim = 2 nodes_facet_map = _nodes_facet_map(mesh) data = [int(0)] * mesh.num_facets() S1 = [0, 1, 2] S2 = [0, 3, 1] S3 = [1, 3, 2] S4 = [2, 3, 0] node_selector = {'S1': S1, 'S2': S2, 'S3': S3, 'S4': S4, } for index, (name, s) in enumerate(surface_sets.items()): cell_face_list = [] for cell_set_name, face_index in s: cell_face_list += [(cell, face_index) for cell in cell_sets[cell_set_name]] for cell, face in cell_face_list: cell_nodes = elems[cell] # Extract the face nodes face_nodes = [cell_nodes[i] for i in node_selector[face]] dolfin_face_nodes = [node_ids_order[n] for n in face_nodes] dolfin_face_nodes.sort() # Convert the face_nodes to dolfin IDs face_id = nodes_facet_map[tuple(dolfin_face_nodes)] data[face_id] = index + 1 # Create and initialise the mesh function handler.start_meshfunction("facet_region", dim, mesh.num_facets() ) for index, physical_region in enumerate (data): handler.add_entity_meshfunction(index, physical_region) handler.end_meshfunction() handler.end_domains()
def gmsh2xml(ifilename, handler): """Convert between .gmsh v2.0 format (http://www.geuz.org/gmsh/) and .xml, parser implemented as a state machine: 0 = read 'MeshFormat' 1 = read mesh format data 2 = read 'EndMeshFormat' 3 = read 'Nodes' 4 = read number of vertices 5 = read vertices 6 = read 'EndNodes' 7 = read 'Elements' 8 = read number of cells 9 = read cells 10 = done Afterwards, extract physical region numbers if they are defined in the mesh file as a mesh function. """ print("Converting from Gmsh format (.msh, .gmsh) to DOLFIN XML format") # The dimension of the gmsh element types supported here as well as the dolfin cell types for each dimension gmsh_dim = {15: 0, 1: 1, 2: 2, 4: 3} cell_type_for_dim = {1: "interval", 2: "triangle", 3: "tetrahedron" } # the gmsh element types supported for conversion supported_gmsh_element_types = [1, 2, 4, 15] # Open files ifile = open(ifilename, "r") # Scan file for cell type cell_type = None highest_dim = 0 line = ifile.readline() while line: # Remove newline line = line.rstrip("\n\r") # Read dimension if line.find("$Elements") == 0: line = ifile.readline() num_elements = int(line) if num_elements == 0: _error("No elements found in gmsh file.") line = ifile.readline() # Now iterate through elements to find largest dimension. Gmsh # format might include elements of lower dimensions in the element list. # We also need to count number of elements of correct dimensions. # Also determine which vertices are not used. dim_count = {0: 0, 1: 0, 2: 0, 3: 0} vertices_used_for_dim = {0: [], 1: [], 2: [], 3: []} # Array used to store gmsh tags for 1D (type 1/line), 2D (type 2/triangular) elements and 3D (type 4/tet) elements tags_for_dim = {0: [], 1: [], 2: [], 3: []} while line.find("$EndElements") == -1: element = line.split() elem_type = int(element[1]) num_tags = int(element[2]) if elem_type in supported_gmsh_element_types: dim = gmsh_dim[elem_type] if highest_dim < dim: highest_dim = dim node_num_list = [int(node) for node in element[3 + num_tags:]] vertices_used_for_dim[dim].extend(node_num_list) if num_tags > 0: tags_for_dim[dim].append(tuple(int(tag) for tag in element[3:3+num_tags])) dim_count[dim] += 1 else: #TODO: output a warning here. "gmsh element type %d not supported" % elem_type pass line = ifile.readline() else: # Read next line line = ifile.readline() # Check that we got the cell type and set num_cells_counted if highest_dim == 0: _error("Unable to find cells of supported type.") num_cells_counted = dim_count[highest_dim] vertex_set = set(vertices_used_for_dim[highest_dim]) vertices_used_for_dim[highest_dim] = None vertex_dict = {} for n,v in enumerate(vertex_set): vertex_dict[v] = n # Step to beginning of file ifile.seek(0) # Set mesh type handler.set_mesh_type(cell_type_for_dim[highest_dim], highest_dim) # Initialise node list (gmsh does not export all vertexes in order) nodelist = {} # Current state state = 0 # Write data num_vertices_read = 0 num_cells_read = 0 # Only import the dolfin objects if facet markings exist process_facets = False if len(tags_for_dim[highest_dim-1]) > 0: # first construct the mesh try: from dolfin import MeshEditor, Mesh except ImportError: _error("DOLFIN must be installed to handle Gmsh boundary regions") mesh = Mesh() mesh_editor = MeshEditor () mesh_editor.open( mesh, highest_dim, highest_dim ) process_facets = True else: # TODO: Output a warning or an error here me = None while state != 10: # Read next line line = ifile.readline() if not line: break # Skip comments if line[0] == '#': continue # Remove newline line = line.rstrip("\n\r") if state == 0: if line == "$MeshFormat": state = 1 elif state == 1: (version, file_type, data_size) = line.split() state = 2 elif state == 2: if line == "$EndMeshFormat": state = 3 elif state == 3: if line == "$Nodes": state = 4 elif state == 4: num_vertices = len(vertex_dict) handler.start_vertices(num_vertices) if process_facets: mesh_editor.init_vertices_global(num_vertices, num_vertices) state = 5 elif state == 5: (node_no, x, y, z) = line.split() node_no = int(node_no) x,y,z = [float(xx) for xx in (x,y,z)] if node_no in vertex_dict: node_no = vertex_dict[node_no] else: continue nodelist[int(node_no)] = num_vertices_read handler.add_vertex(num_vertices_read, [x, y, z]) if process_facets: if highest_dim == 1: coords = numpy.array([x]) elif highest_dim == 2: coords = numpy.array([x, y]) elif highest_dim == 3: coords = numpy.array([x, y, z]) mesh_editor.add_vertex(num_vertices_read, coords) num_vertices_read +=1 if num_vertices == num_vertices_read: handler.end_vertices() state = 6 elif state == 6: if line == "$EndNodes": state = 7 elif state == 7: if line == "$Elements": state = 8 elif state == 8: handler.start_cells(num_cells_counted) if process_facets: mesh_editor.init_cells_global(num_cells_counted, num_cells_counted) state = 9 elif state == 9: element = line.split() elem_type = int(element[1]) num_tags = int(element[2]) if elem_type in supported_gmsh_element_types: dim = gmsh_dim[elem_type] else: dim = 0 if dim == highest_dim: node_num_list = [vertex_dict[int(node)] for node in element[3 + num_tags:]] for node in node_num_list: if not node in nodelist: _error("Vertex %d of %s %d not previously defined." % (node, cell_type_for_dim[dim], num_cells_read)) cell_nodes = [nodelist[n] for n in node_num_list] handler.add_cell(num_cells_read, cell_nodes) if process_facets: cell_nodes = numpy.array([nodelist[n] for n in node_num_list], dtype=numpy.uintp) mesh_editor.add_cell(num_cells_read, cell_nodes) num_cells_read +=1 if num_cells_counted == num_cells_read: handler.end_cells() if process_facets: mesh_editor.close() state = 10 elif state == 10: break # Write mesh function based on the Physical Regions defined by # gmsh, but only if they are not all zero. All zero physical # regions indicate that no physical regions were defined. if highest_dim not in [1,2,3]: _error("Gmsh tags not supported for dimension %i. Probably a bug" % dim) tags = tags_for_dim[highest_dim] physical_regions = tuple(tag[0] for tag in tags) if not all(tag == 0 for tag in physical_regions): handler.start_meshfunction("physical_region", dim, num_cells_counted) for i, physical_region in enumerate(physical_regions): handler.add_entity_meshfunction(i, physical_region) handler.end_meshfunction() # Now process the facet markers tags = tags_for_dim[highest_dim-1] if (len(tags) > 0) and (mesh is not None): physical_regions = tuple(tag[0] for tag in tags) if not all(tag == 0 for tag in physical_regions): mesh.init(highest_dim-1,0) # Get the facet-node connectivity information (reshape as a row of node indices per facet) if highest_dim==1: # for 1d meshes the mesh topology returns the vertex to vertex map, which isn't what we want # as facets are vertices facets_as_nodes = numpy.array([[i] for i in range(mesh.num_facets())]) else: facets_as_nodes = mesh.topology()(highest_dim-1,0)().reshape ( mesh.num_facets(), highest_dim ) # Build the reverse map nodes_as_facets = {} for facet in range(mesh.num_facets()): nodes_as_facets[tuple(facets_as_nodes[facet,:])] = facet data = [int(0*k) for k in range(mesh.num_facets()) ] for i, physical_region in enumerate(physical_regions): nodes = [n-1 for n in vertices_used_for_dim[highest_dim-1][highest_dim*i:(highest_dim*i+highest_dim)]] nodes.sort() if physical_region != 0: try: index = nodes_as_facets[tuple(nodes)] data[index] = physical_region except IndexError: raise Exception ( "The facet (%d) was not found to mark: %s" % (i, nodes) ) # Create and initialise the mesh function handler.start_meshfunction("facet_region", highest_dim-1, mesh.num_facets() ) for index, physical_region in enumerate ( data ): handler.add_entity_meshfunction(index, physical_region) handler.end_meshfunction() # Check that we got all data if state == 10: print("Conversion done") else: _error("Missing data, unable to convert \n\ Did you use version 2.0 of the gmsh file format?") # Close files ifile.close()
def convert(ifilename, handler): """ Convert from Abaqus. The Abaqus format first defines a node block, then there should be a number of elements containing these nodes. """ # Dictionary of nodes (maps node id to coordinates) nodes = {} # Dictionary of elements (maps cell id to list of cell nodes) elems = {} # Lists of nodes for given name (key) node_sets = {} # Lists of cells for given name (key) cell_sets = {} # Lists of surfaces for given name (key) in the format: # {'SS1': [set(['SS1_S1', 'S1']), set(['SS1_S4', 'S4'])]}, # where SS1 is the name of the surface, SS1_S1 is the name of the # cell list whose first face is to be selected, ... surface_sets = {} # Open file Abaqus file file = open(ifilename, 'r') csv_file = csv.reader(file, delimiter=',', skipinitialspace=True) node_set_name = None generate = None # Set intial state state state = State.Init # Read data from input file for l in csv_file: # Sanity check if (len(l) == 0): print("Ooops, zero length.") if l[0].startswith('**'): # Pass over comments continue elif l[0].startswith('*'): # Have a keyword state = State.Unknown if l[0].lower() == "*heading": state = State.ReadHeading elif l[0].lower() == "*part": part_name = _read_part_name(l) elif l[0].lower() == "*end part": state = State.Invalid elif l[0].lower() == "*node": node_set_name = _create_node_list_entry(node_sets, l) state = State.ReadNodes elif l[0].lower() == "*element": cell_type, cell_set_name = _read_element_keywords(cell_sets, l) state = State.ReadCells elif l[0].lower() == "*nset": node_set_name, generate = _read_nset_keywords(node_sets, l) state = State.ReadNodeSet elif l[0].lower() == "*elset": cell_set_name, generate = _read_elset_keywords(cell_sets, l) if generate: print("WARNING: generation of *elsets not tested.") state = State.ReadCellSet elif l[0].lower() == "*surface": surface_set_name, generate = _read_surface_keywords( surface_sets, l) state = State.ReadSurfaceSet else: print("WARNING: unrecognised Abaqus input keyword:", l[0]) state = State.Unknown else: if state == State.ReadHeading: model_name = _read_heading(l) elif state == State.ReadNodes: node_id = int(l[0]) - 1 coords = [float(c) for c in l[1:]] nodes[node_id] = coords if node_set_name is not None: node_sets[node_set_name].add(node_id) elif state == State.ReadCells: cell_id = int(l[0]) - 1 cell_connectivity = [int(v) - 1 for v in l[1:]] elems[cell_id] = cell_connectivity if cell_set_name is not None: cell_sets[cell_set_name].add(cell_id) elif state == State.ReadNodeSet: try: if generate: n0, n1, increment = l node_range = list( range(int(n0) - 1, int(n1) - 1, int(increment))) node_range.append(int(n1) - 1) node_sets[node_set_name].update(node_range) else: # Strip empty term at end of list, if present if l[-1] == '': l.pop(-1) node_range = [int(n) - 1 for n in l] node_sets[node_set_name].update(node_range) except: print("WARNING: Non-integer node sets not yet supported.") elif state == State.ReadCellSet: try: if generate: n0, n1, increment = l cell_range = list( range(int(n0) - 1, int(n1) - 1, int(increment))) cell_range.append(int(n1) - 1) cell_sets[cell_set_name].update(cell_range) else: # Strip empty term at end of list, if present if l[-1] == '': l.pop(-1) cell_range = [int(n) - 1 for n in l] cell_sets[cell_set_name].update(cell_range) except: print( "WARNING: Non-integer element sets not yet supported.") elif state == State.ReadSurfaceSet: # Strip empty term at end of list, if present if l[-1] == '': l.pop(-1) surface_sets[surface_set_name].update([tuple(l)]) elif state == State.Invalid: # part raise Exception("Inavlid Abaqus parser state..") # Close CSV object file.close() del csv_file # Write data to XML file # Note that vertices/cells must be consecutively numbered, which # isn't necessarily the case in Abaqus. Therefore we enumerate and # translate original IDs to sequence indexes if gaps are present. # FIXME handler.set_mesh_type("tetrahedron", 3) process_facets = len(surface_sets) > 0 if process_facets: try: from dolfin import MeshEditor, Mesh except ImportError: _error( "DOLFIN must be installed to handle Abaqus boundary regions") mesh = Mesh() mesh_editor = MeshEditor() mesh_editor.open(mesh, 3, 3) node_ids_order = {} # Check for gaps in vertex numbering node_ids = list(iterkeys(nodes)) if len(node_ids) > 0: vertex_gap = (min(node_ids) != 0 or max(node_ids) != len(node_ids) - 1) for x, y in enumerate(node_ids): node_ids_order[y] = x # Maps Abaqus IDs to Dolfin IDs else: vertex_gap = True # Check for gaps in cell numbering elemids = list(iterkeys(elems)) if len(elemids) > 0: cell_gap = (min(elemids) != 0 or max(elemids) != len(elemids) - 1) else: cell_gap = True # Write vertices to XML file handler.start_vertices(len(nodes)) if process_facets: mesh_editor.init_vertices_global(len(nodes), len(nodes)) if not vertex_gap: for v_id, v_coords in list(iteritems(nodes)): handler.add_vertex(v_id, v_coords) if process_facets: mesh_editor.add_vertex(v_id, np.array(v_coords, dtype=np.float_)) else: for idx, (v_id, v_coords) in enumerate(iteritems(nodes)): handler.add_vertex(idx, v_coords) if process_facets: mesh_editor.add_vertex(idx, np.array(v_coords, dtype=np.float_)) handler.end_vertices() # Write cells to XML file handler.start_cells(len(elems)) if process_facets: mesh_editor.init_cells_global(len(elems), len(elems)) if not vertex_gap and not cell_gap: for c_index, c_data in list(iteritems(elems)): for v_id in c_data: if not (0 <= v_id < len(nodes)): handler.error( "Element %s references non-existent node %s" % (c_index, v_id)) handler.add_cell(c_index, c_data) if process_facets: c_data_tmp = np.array(c_data) c_data_tmp.sort() mesh_editor.add_cell(c_index, np.array(c_data_tmp, dtype=np.uintp)) elif not vertex_gap and cell_gap: for idx, (c_index, c_data) in enumerate(iteritems(elems)): for v_id in c_data: if not (0 <= v_id < len(nodes)): handler.error( "Element %s references non-existent node %s" % (c_index, v_id)) handler.add_cell(idx, c_data) if process_facets: c_data_tmp = np.array(c_data) c_data_tmp.sort() mesh_editor.add_cell(idx, np.array(c_data_tmp, dtype=np.uintp)) else: for idx, (c_id, c_data) in enumerate(iteritems(elems)): c_nodes = [] for v_id in c_data: try: c_nodes.append(node_ids_order[v_id]) except ValueError: handler.error( "Element %s references non-existent node %s" % (c_id, v_id)) handler.add_cell(idx, c_nodes) if process_facets: c_nodes.sort() mesh_editor.add_cell(idx, np.array(c_nodes, dtype=np.uintp)) handler.end_cells() # Write MeshValueCollections to XML file handler.start_domains() # Build a abaqus node ID -> dolfin cell ID map (which is not unique but that is irrelevant here) # and its local entity. if len(node_sets) > 0: node_cell_map = {} for c_dolfin_index, (c_index, c_data) in enumerate(iteritems(elems)): c_data_tmp = np.array(c_data) c_data_tmp.sort() for local_entity, n_index in enumerate(c_data_tmp): node_cell_map[n_index] = (c_dolfin_index, local_entity) # Write vertex/node sets dim = 0 for value, (name, node_set) in enumerate(iteritems(node_sets)): handler.start_mesh_value_collection(name, dim, len(node_set), "uint") for node in node_set: try: cell, local_entity = node_cell_map[node] handler.add_entity_mesh_value_collection( dim, cell, value, local_entity=local_entity) except KeyError: print("Warning: Boundary references non-existent node %s" % node) handler.end_mesh_value_collection() # Write cell/element sets dim = 3 for name, s in list(iteritems(cell_sets)): handler.start_mesh_value_collection(name, dim, len(s), "uint") for cell in s: handler.add_entity_mesh_value_collection(dim, cell, 0) handler.end_mesh_value_collection() # Write surface sets if process_facets: dim = 2 nodes_facet_map = _nodes_facet_map(mesh) data = [int(0)] * mesh.num_facets() S1 = [0, 1, 2] S2 = [0, 3, 1] S3 = [1, 3, 2] S4 = [2, 3, 0] node_selector = { 'S1': S1, 'S2': S2, 'S3': S3, 'S4': S4, } for index, (name, s) in enumerate(iteritems(surface_sets)): cell_face_list = [] for cell_set_name, face_index in s: cell_face_list += [(cell, face_index) for cell in cell_sets[cell_set_name]] for cell, face in cell_face_list: cell_nodes = elems[cell] # Extract the face nodes face_nodes = [cell_nodes[i] for i in node_selector[face]] dolfin_face_nodes = [node_ids_order[n] for n in face_nodes] dolfin_face_nodes.sort() # Convert the face_nodes to dolfin IDs face_id = nodes_facet_map[tuple(dolfin_face_nodes)] data[face_id] = index + 1 # Create and initialise the mesh function handler.start_meshfunction("facet_region", dim, mesh.num_facets()) for index, physical_region in enumerate(data): handler.add_entity_meshfunction(index, physical_region) handler.end_meshfunction() handler.end_domains()
mesh = Mesh() editor = MeshEditor() editor.open(mesh, 2, 2) # topo_dim = 2, geom dim = 2 editor.init_vertices(6) editor.init_cells(2) vertex_0 = Vertex(mesh, 0) vertex_1 = Vertex(mesh, 1) vertex_2 = Vertex(mesh, 2) vertex_3 = Vertex(mesh, 3) vertex_4 = Vertex(mesh, 4) vertex_5 = Vertex(mesh, 5) editor.add_cell(0, 1, 2, 3) editor.add_cell(1, 0, 2, 3) editor.close() t = IonTag("foo", 3, "int", mesh) for v in vertices(mesh): t[v] = [1, 2, 3] for c in cells(mesh): t[c] = [4, 5, 6, 7] v = MeshEntity(mesh, 0, 1)
def _fit_dolfin(x0, y0, points, cells, lmbda: float, degree: int = 1, solver: str = "lsqr"): from dolfin import ( BoundingBoxTree, Cell, EigenMatrix, FacetNormal, Function, FunctionSpace, Mesh, MeshEditor, Point, TestFunction, TrialFunction, assemble, dot, ds, dx, grad, ) def _assemble_eigen(form): L = EigenMatrix() assemble(form, tensor=L) return L def _build_eval_matrix(V, points): """Build the sparse m-by-n matrix that maps a coefficient set for a function in V to the values of that function at m given points.""" # See <https://www.allanswered.com/post/lkbkm/#zxqgk> mesh = V.mesh() bbt = BoundingBoxTree() bbt.build(mesh) dofmap = V.dofmap() el = V.element() sdim = el.space_dimension() rows = [] cols = [] data = [] for i, x in enumerate(points): cell_id = bbt.compute_first_entity_collision(Point(*x)) cell = Cell(mesh, cell_id) coordinate_dofs = cell.get_vertex_coordinates() rows.append(np.full(sdim, i)) cols.append(dofmap.cell_dofs(cell_id)) v = el.evaluate_basis_all(x, coordinate_dofs, cell_id) data.append(v) rows = np.concatenate(rows) cols = np.concatenate(cols) data = np.concatenate(data) m = len(points) n = V.dim() matrix = sparse.csr_matrix((data, (rows, cols)), shape=(m, n)) return matrix editor = MeshEditor() mesh = Mesh() # Convert points, cells to dolfin mesh if cells.shape[1] == 2: editor.open(mesh, "interval", 1, 1, 1) else: # can only handle triangles for now assert cells.shape[1] == 3 # topological and geometrical dimension 2 editor.open(mesh, "triangle", 2, 2, 1) editor.init_vertices(len(points)) editor.init_cells(len(cells)) for k, point in enumerate(points): editor.add_vertex(k, point) for k, cell in enumerate(cells.astype(np.uintp)): editor.add_cell(k, cell) editor.close() V = FunctionSpace(mesh, "CG", degree) u = TrialFunction(V) v = TestFunction(V) mesh = V.mesh() n = FacetNormal(mesh) # omega = assemble(1 * dx(mesh)) A = _assemble_eigen(dot(grad(u), grad(v)) * dx - dot(n, grad(u)) * v * ds).sparray() A *= lmbda E = _build_eval_matrix(V, x0) # mass matrix M = _assemble_eigen(u * v * dx).sparray() x = _solve(A, M, E, y0, solver) u = Function(V) u.vector().set_local(x) return u