def _are_connected_by_edge(self, v1, v2): """Returns true if both vertices are connected by an edge. """ for edge1 in dolfin.edges(v1): for edge2 in dolfin.edges(v2): if edge1.index() == edge2.index(): # Vertices are connected by edge return True return False
def poincare_const(o, p, d=1): # Vectorial Poincare, see [Blechta, Malek, Vohralik 2016] if d != 1 and p != 2.0: return d**abs(0.5-1.0/p) * poincare_const(o, p) if isinstance(o, Mesh): raise NotImplementedError("Poincare constant not implemented on mesh!") if isinstance(o, Cell): assert _is_simplex(o), "Poincare constant not " \ "implemented on non-simplicial cells!" h = max(e.length() for e in edges(o)) return h*_poincare_convex(p) if isinstance(o, CellType): assert _is_simplex(o), "Poincare constant not " \ "implemented on non-simplicial cells!" return _poincare_convex(p) if isinstance(o, Vertex): # TODO: fix using ghosted mesh not_working_in_parallel("Poincare computation on patch") h = max(v0.point().distance(v1.point()) for c0 in cells(o) for v0 in vertices(c0) for c1 in cells(o) for v1 in vertices(c1)) # FIXME: Implement a check for convexity of the patch _warn_poincare_convex() return h*_poincare_convex(p) raise NotImplementedError
def shape(self, mesh, size=50): """Build mesh.""" vf = np.vectorize(self.f) x = mesh.coordinates()[:, 0] y = mesh.coordinates()[:, 1] a = np.arctan2(y, x) x, y = [x * vf(a), y * vf(a)] mesh.coordinates()[:] = np.array([x, y]).transpose() boundary = BoundaryMesh(mesh, 'exterior') boundary.init() lst = [0] vs = list(vertices(boundary)) while True: v = vs[lst[-1]] neighbors = set() for e in edges(v): neighbors.update(e.entities(0)) neighbors.remove(v.index()) neighbors = list(neighbors) k = 0 if len(lst) > 1: if neighbors[0] == lst[-2]: k = 1 lst.append(neighbors[k]) if lst[-1] == lst[0]: break lst = lst[:-1] points = boundary.coordinates()[lst] points = [Point(*p) for p in points] try: polygon = Polygon(points) except: polygon = Polygon(points[::-1]) return generate_mesh(polygon, size)
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 curvilinear_coordinate_1d(mb, p0=0, function=None): "Returns parametrization of a curve" # edge-to-vertex connectivity EE = np.zeros((mb.num_cells(), mb.num_vertices()), dtype=bool) for e in edges(mb): EE[e.index(), e.entities(0)] = True # vertex-to-vertex connectivity (via edges) PP = EE.T @ EE np.fill_diagonal(PP, False) mmap = -np.ones(PP.shape[0], dtype=int) # order vertices mmap[0] = p0 for k in range(PP.shape[0] - 1): neig = np.where(PP[mmap[k], :])[0] mmap[k + 1] = neig[1] if neig[0] in mmap else neig[0] # cumulative length of edges l = np.linalg.norm(np.diff(mb.coordinates()[mmap, :], axis=0), axis=1) s = np.r_[0, np.cumsum(l)] if function is None: P1e = FiniteElement("CG", mb.ufl_cell(), 1) Ve = FunctionSpace(mb, P1e) function = Function(Ve) function.vector()[vertex_to_dof_map(Ve)[mmap]] = s return function else: Ve = function.function_space() function.vector()[vertex_to_dof_map(Ve)[mmap]] = s
def build_cell_to_edge(V): '''Build mapping between cell and edges that form it.''' cell_to_edge = {} mesh = V.mesh() mesh.init(1) for cell in cells(mesh): cell_to_edge[cell.index()] = [] for edge in edges(cell): cell_to_edge[cell.index()].append(edge.index()) return cell_to_edge
def start(self): n, m = self.values.shape dofs = [] for j in range(m): dofs.append(self.function_space.sub(j).dofmap().dofs(self.mesh, 1)) for edge in edges(self.mesh): i = edge.global_index() p = edge.midpoint() for j in range(m): dof = dofs[j][i] self.values[i, j] = self.solution[dof] self.points[i, :] = [p.x(), p.y(), p.z()]
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 mesh_info(sim): """ Return a string containing some basic information about the mesh (such as the number of cells, interior/surface triangles, vertices, etc.). Also print a distribution of edge lengths present in the mesh and how they compare to the exchange length, the Bloch parameter and the Helical period (if these can be computed, which requires an exchange interaction (plus anisotropy for the Bloch parameter and DMI value for the Helical period)); note that for spatially varying material parameters the average values are used). This information is relevant to estimate whether the mesh discretisation is too coarse and might result in numerical artefacts (see W. Rave, K. Fabian, A. Hubert, "Magnetic states ofsmall cubic particles with uniaxial anisotropy", J. Magn. Magn. Mater. 190 (1998), 332-348). """ info_string = "{}\n".format(mesh_information(sim.mesh)) edgelengths = [e.length() * sim.unit_length for e in df.edges(sim.mesh)] lengths = _get_length_scales(sim) def added_info(name, L): (a, b), _ = np.histogram(edgelengths, bins=[0, L, np.infty]) if b == 0.0: msg = "All edges are shorter" msg2 = "" else: msg = "Warning: {:.2f}% of edges are longer".format(100.0 * b / (a + b)) msg2 = " (this may lead to discretisation artefacts)" info = "{} than the {} = {:.2f} nm{}.\n".format( msg, name, L * 1e9, msg2) return info if not (sim.has_interaction('Exchange')): info_string += "Warning: Simulation object has no exchange. Cannot compute exchange length(s).\n" else: for key, value in lengths.items(): info_string += added_info(key, value) info_string += "\nThe minimum length is the {} = {:.2f}nm".format( min(lengths, key=lengths.get), min(lengths.values()) * 1e9) return info_string
def eikonal_1d(mb, p0=0, function=None): "Compute distance from p0 on set of edges" # edge-to-vertex connectivity EE = np.zeros((mb.num_cells(), mb.num_vertices()), dtype=bool) for e in edges(mb): EE[e.index(), e.entities(0)] = True # vertex-to-vertex connectivity (via edges) PP = EE.T @ EE np.fill_diagonal(PP, False) # initial solution is inf everywhere sol = np.empty(PP.shape[0]) sol.fill(np.inf) # initial conditions active = deque([p0]) sol[p0] = 0.0 # fast marching on edges x = mb.coordinates() while active: curr = active.pop() neig = np.where(PP[curr, :])[0] ll = sol[curr] + np.linalg.norm(x[neig, :] - x[curr, :], axis=1) up = neig[ll < sol[neig]] active.extend(up) sol[neig] = np.minimum(sol[neig], ll) # return solution if function is None: P1e = FiniteElement("CG", mb.ufl_cell(), 1) Ve = FunctionSpace(mb, P1e) function = Function(Ve) function.vector()[vertex_to_dof_map(Ve)] = sol return function else: Ve = function.function_space() function.vector()[vertex_to_dof_map(Ve)] = sol
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)
def fun(mesh3d, npoints): '''A random curve starting close to (-1, -1, -1) and continueing inside''' import networkx as nx import random edge_f = df.MeshFunction('size_t', mesh3d, 1, 0) mesh3d.init(1, 0) # Init the graph G = nx.Graph() edge_indices = { tuple(sorted(e.entities(0).tolist())): e_index for e_index, e in enumerate(df.edges(mesh3d)) } G.add_edges_from(iter(edge_indices.keys())) # Let's find boundary vertices V = df.FunctionSpace(mesh3d, 'CG', 1) bdry = df.CompiledSubDomain( 'near(std::max(std::max(std::abs(x[0]), std::abs(x[1])), std::abs(x[2])), 1, tol)', tol=TOL) bc = df.DirichletBC(V, df.Constant(0), bdry, 'pointwise') bc_vertices = set( df.dof_to_vertex_map(V)[list(bc.get_boundary_values().keys())]) # Start at the boundary at (-1, -1, 1) X = mesh3d.coordinates() start = np.argmin(np.sum((X - np.array([-1, -1, -1]))**2, axis=1)) # All vertices vertices = list(range(mesh3d.num_vertices())) first = None while npoints: # Pick the next vertex, inside while True: stop = random.choice(vertices) if start != stop and stop not in bc_vertices: break # The path is a shortest path between vertices path = nx.shortest_path(G, source=start, target=stop) # Here it can happen that the path will have surface points if first is None: # So we walk back (guaranteed to be in) until we hit the surface clean_path = [] for p in reversed(path): clean_path.append(p) if p in bc_vertices: print('Shifted start to', X[p]) first = p break path = clean_path start = first # Start in, must end in and stay in else: if set(path) & bc_vertices: continue for v0, v1 in zip(path[:-1], path[1:]): edge = (v0, v1) if v0 < v1 else (v1, v0) edge_f[edge_indices[edge]] = 1 start = stop npoints -= 1 # df.File('x.pvd') << edge_f return edge_f, X[first]
def assemble_2d(mesh): v0, v1, v2, divs = compute_nodal_triangle() cs = mesh.coordinates() BDM = df.FunctionSpace(mesh, "BDM", 1) fun = df.Function(BDM) n = fun.vector().size() mat = sp.lil_matrix((n, n)) m = mesh.num_cells() mat_K = sp.lil_matrix((n, m)) map = BDM.dofmap() for cell in df.cells(mesh): i = cell.entities(0) cm = [] cm.append(cs[i[1]] - cs[i[0]]) cm.append(cs[i[2]] - cs[i[0]]) A = np.transpose(np.array(cm)) B = np.dot(np.transpose(A), A) J = np.linalg.det(A) K = B / abs(J) cfs = map.cell_dofs(cell.index()) for i in range(6): for j in range(6): existing = mat[cfs[i], cfs[j]] add_new = np.dot(np.dot(K,v0[i]),v0[j]) \ + np.dot(np.dot(K,v1[i]),v1[j]) \ + np.dot(np.dot(K,v2[i]),v2[j]) mat[cfs[i], cfs[j]] = existing + add_new / 6.0 id_c = cell.index() for j in range(6): existing = mat_K[cfs[j], id_c] if J > 0: mat_K[cfs[j], id_c] = existing + divs[j] else: mat_K[cfs[j], id_c] = existing - divs[j] idy = generate_nonzero_ids(mat) #set the Neumann boundary condition here mesh.init(1, 2) for edge in df.edges(mesh): faces = edge.entities(2) if len(faces) == 1: f = df.Face(mesh, faces[0]) cfs = map.cell_dofs(f.index()) ids = map.tabulate_facet_dofs(f.index(edge)) zid = cfs[ids] for i in zid: mat[i, idy[i]] = 0 mat[idy[i], i] = 0 mat[i, i] = 1 A_inv = spl.inv(mat.tocsc()) K3 = A_inv * mat_K.tocsr() K3 = K3.tolil() idy = generate_nonzero_ids(K3) mesh.init(1, 2) for edge in df.edges(mesh): faces = edge.entities(2) if len(faces) == 1: f = df.Face(mesh, faces[0]) cfs = map.cell_dofs(f.index()) ids = map.tabulate_facet_dofs(f.index(edge)) for i in cfs[ids]: K3[i, idy[i]] = 0 K1 = mat_K.transpose() K = K1 * K3.tocsr() DG = df.FunctionSpace(mesh, "DG", 0) v = df.TestFunction(DG) L = df.assemble(v * df.dx).array() return K, L
def test_convert_triangle( self): # Disabled because it fails, see FIXME below # test no. 1 from dolfin import Mesh, MPI fname = os.path.join(os.path.dirname(__file__), "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 fname = os.path.join(os.path.dirname(__file__), "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 MeshFunction and assign the values based on the # converted Meshfunction cf = MeshFunction("size_t", mesh, mesh.topology().dim()) 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() edge_markers = mesh.domains().markers(mesh.topology().dim() - 1) self.assertTrue(edge_markers is not None) #length0 = reduce(add, (Edge(mesh, e.index()).length() \ # for e in SubsetIterator(edge_markers, 0)), 0.0) length0, length1 = 0.0, 0.0 for item in list(edge_markers.items()): if item[1] == 0: e = Edge(mesh, int(item[0])) length0 += Edge(mesh, int(item[0])).length() elif item[1] == 1: length1 += Edge(mesh, int(item[0])).length() # 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)
def calcs(fname): data = pickle.load(open(fname+'.pickle')) mesh = dolfin.Mesh(data['meshfile']) elen = np.array([e.length() for e in dolfin.edges(mesh)]) ave_elen = np.average(elen) material_meshfn = dolfin.MeshFunction('uint', mesh, data['materialsfile']) V = dolfin.FunctionSpace(mesh, "Nedelec 1st kind H(curl)", data['order']) x = data['x'] x_r = as_dolfin_vector(x.real) x_i = as_dolfin_vector(x.imag) E_r = dolfin.Function(V, x_r) E_i = dolfin.Function(V, x_i) k0 = 2*np.pi*data['freq']/c0 n = V.cell().n ReS = (1/k0/Z0)*dolfin.dot(n, (dolfin.cross(E_r, -dolfin.curl(E_i)) + dolfin.cross(E_i, dolfin.curl(E_r))))*dolfin.ds energy_flux = dolfin.assemble(ReS) surface_flux = SurfaceFlux(V) surface_flux.set_dofs(x) surface_flux.set_k0(k0) energy_flux2 = surface_flux.calc_flux() assert(np.allclose(energy_flux, energy_flux2, rtol=1e-8, atol=1e-8)) def boundary(x, on_boundary): return on_boundary E_r_dirich = dolfin.DirichletBC(V, E_r, boundary) x_r_dirich = as_dolfin_vector(np.zeros(len(x))) E_r_dirich.apply(x_r_dirich) E_i_dirich = dolfin.DirichletBC(V, E_i, boundary) x_i_dirich = as_dolfin_vector(np.zeros(len(x))) E_i_dirich.apply(x_i_dirich) x_dirich = x_r_dirich.array() + 1j*x_i_dirich.array() emfunc = CalcEMFunctional(V) emfunc.set_k0(k0) cell_domains = dolfin.CellFunction('uint', mesh) cell_domains.set_all(0) cell_region = 1 boundary_cells = Geometry.BoundaryEdgeCells(mesh) boundary_cells.mark(cell_domains, cell_region) emfunc.set_cell_domains(cell_domains, cell_region) emfunc.set_E_dofs(x) emfunc.set_g_dofs(1j*x_dirich.conjugate()/k0/Z0) var_energy_flux = emfunc.calc_functional().conjugate() var_surf_flux = VariationalSurfaceFlux(V) var_surf_flux.set_dofs(x) var_surf_flux.set_k0(k0) var_energy_flux2 = var_surf_flux.calc_flux() assert(np.allclose(var_energy_flux, var_energy_flux2, rtol=1e-8, atol=1e-8)) complex_voltage = ComplexVoltageAlongLine(V) complex_voltage.set_dofs(x) volts = complex_voltage.calculate_voltage(*data['source_endpoints']) result = dict(h=ave_elen, order=order, volts=volts, sflux=energy_flux, vflux=var_energy_flux) print 'source power: ', volts*data['I'] print 'energy flux: ', energy_flux print 'var energy flux: ', var_energy_flux # print '|'.join(str(s) for s in ('', volts*data['I'], energy_flux, # var_energy_flux, '')) return result
def topology_1d(self) -> np.ndarray: """ Get mesh edge topology (lines) :return: 1D topology """ return np.array(list(map(lambda x: x.entities(0), df.edges(self.mesh))))