def test_make_1(): coords = np.array([[0, 0], [1, 0], [1, 1], [0, 1.]]) mesh = make_line_mesh(coords, close_path=True) assert np.linalg.norm(mesh.coordinates() - coords) < 1E-13 cells = np.array([[0, 1], [1, 2], [2, 3], [0, 3]]) assert np.linalg.norm(mesh.cells() - cells) < 1E-13, mesh.cells()
def stitch(mesh, edges): '''Remove edge and stitch together vertices''' assert mesh.topology().dim() == 1 vertices = list(range(mesh.num_vertices())) # We want to rewrite this such that given edges are # kept but based on their connectivity we perform stitches # changing other cells e2v = mesh.topology()(1, 0) # NOTE: by saying that edge is to be removed we're saying that its # vertices can be regarded as same. A piece of graph of connected # edges is thus a substitution rule that all vertices in that piece # can be condensed g = nx.Graph() g.add_edges_from(map(e2v, edges)) rules = {} # Substitution rule for cc in sorted(nx.algorithms.connected_components(g), key=len): substitute = cc.pop() for node in cc: assert node not in rules rules[node] = substitute # Edges are definitely part of the new mesh. Some other cells might # be added as well if substitution produces two equal nodes edges = list(edges) # We want to keep a mapping from new mesh cell_idx to what was approx # the parent cells in the oritinal mesh cell_map, new_cells = [], [] # Now we rewrite cells = mesh.cells().tolist() for cell_id, cell in enumerate(cells): if cell_id not in edges: # Subs if cell[0] in rules: cell[0] = rules[cell[0]] if cell[1] in rules: cell[1] = rules[cell[1]] # Invalid cell[0] == cell[1] and edges.append(cell_id) # A valid cell will keep it's position in new mesh if cell[0] != cell[1]: cell_map.append(cell_id) new_cells.append(cell) # Which vertices will be used; this is also a map from new to old vertex_map = list(set(sum(new_cells, []))) # Need to finally rewrte the cells this way; so vertex old -> new needed ivertex_map = {o: n for n, o in enumerate(vertex_map)} new_cells = np.fromiter((ivertex_map[v] for v in sum(new_cells, [])), dtype='uintp').reshape((-1, 2)) new_coordinates = mesh.coordinates()[vertex_map] return make_line_mesh(new_coordinates, new_cells), cell_map, vertex_map
def test_make_2(): coords = np.array([[0, 0, 2], [1, 0, 2], [1, 1, 2], [0, 1., 2]]) cells = np.array([[0, 1], [1, 2], [2, 3], [3, 0], [0, 2]]) mesh = make_line_mesh(coords, cells=cells) assert np.linalg.norm(mesh.coordinates() - coords) < 1E-13 cells = np.array([[0, 1], [1, 2], [2, 3], [0, 3], [0, 2]]) cells0 = np.array(map(sorted, mesh.cells())) assert np.linalg.norm(cells0 - cells) < 1E-13, mesh.cells() assert mesh.ufl_cell() == ufl.Cell('interval', 3)
def refine(mesh, threshold): '''Refine such that the new mesh has cell size of at most dx''' assert mesh.topology().dim() == 1 e2v = mesh.topology()(1, 0) cells = {old: [c.tolist()] for old, c in enumerate(mesh.cells())} x = mesh.coordinates() lengths = edge_lengths(mesh) needs_refine = find_edges(lengths, predicate=lambda v, x: v > threshold) next_v = len(x) for cell in needs_refine: v0, v1 = cells[cell].pop() x0, x1 = x[v0], x[v1] l = np.linalg.norm(x0 - x1) nodes = [v0] ts = np.linspace(0., 1., int(ceil(l / threshold)) + 1)[1:-1] dx = x1 - x0 for t in ts: xmid = x0 + t * dx x = np.row_stack([x, xmid]) nodes.append(next_v) next_v += 1 nodes.append(v1) cells[cell] = list(zip(nodes[:-1], nodes[1:])) # Mapping for parent_cell_map = sum(([k] * len(cells[k]) for k in sorted(cells)), []) cells = np.array(sum((cells[k] for k in sorted(cells)), []), dtype='uintp') mesh = make_line_mesh(x, cells) return mesh, np.array(parent_cell_map, dtype='uintp')
def curve_distance(edge_f, nlayers=4, outside_val=-1): ''' Compute distance (P1) function that has for each vertex distance from curve edge_f == 1. ''' # Want to build a P1 function mesh = edge_f.mesh() V = df.FunctionSpace(mesh, 'CG', 1) d = df.Function(V) d_values = d.vector().get_local() # Default d_values[:] = outside_val # Want to set points layer by layer v2d = df.vertex_to_dof_map(V) layers = layer_neighbor_vertex_generator(edge_f, nlayers=nlayers + 1) curve_points = next(layers) # On curve is 0 d_values[v2d[list(curve_points)]] = 0. x = mesh.coordinates() # For others we need to compute distance from edges mesh.init(1, 0) e2v = mesh.topology()(1, 0) segments = np.row_stack(map(e2v, np.where(edge_f.array() == 1)[0])) # In local numbering vtx_idx, segments = np.unique(segments.flatten(), return_inverse=True) line_mesh = make_line_mesh(x[vtx_idx], segments.reshape((-1, 2))) tree = line_mesh.bounding_box_tree() for points in map(list, layers): d_values[v2d[points]] = np.fromiter( (tree.compute_closest_entity(df.Point(x[p]))[1] for p in points), dtype=float) d.vector().set_local(d_values) return d
def test(): coords = np.array([[0, 0], [1, 0], [1, 0.2], [1, 0.5], [1, 0.7], [1, 1], [0, 1.]]) mesh = make_line_mesh(coords, close_path=True) rmesh, mapping = refine(mesh, threshold=0.6) x = mesh.coordinates() y = rmesh.coordinates() assert np.linalg.norm(x - y[:len(x)]) < 1E-13 e2v, E2V = mesh.topology()(1, 0), rmesh.topology()(1, 0) for c in range(mesh.num_cells()): x0, x1 = x[e2v(c)] e = x1 - x0 e = e / np.linalg.norm(e) for C in np.where(mapping == c)[0]: y0, y1 = y[E2V(C)] E = y1 - y0 E = E / np.linalg.norm(E) assert abs(1 - abs(np.dot(e, E))) < 1E-13
# Mapping for parent_cell_map = sum(([k] * len(cells[k]) for k in sorted(cells)), []) cells = np.array(sum((cells[k] for k in sorted(cells)), []), dtype='uintp') mesh = make_line_mesh(x, cells) return mesh, np.array(parent_cell_map, dtype='uintp') # -------------------------------------------------------------------- if __name__ == '__main__': coords = np.array([[0, 0], [1, 0], [1, 0.2], [1, 0.5], [1, 0.7], [1, 1], [0, 1.]]) mesh = make_line_mesh(coords, close_path=True) rmesh, mapping = refine(mesh, threshold=0.6) x = mesh.coordinates() y = rmesh.coordinates() assert np.linalg.norm(x - y[:len(x)]) < 1E-13 e2v, E2V = mesh.topology()(1, 0), rmesh.topology()(1, 0) for c in range(mesh.num_cells()): x0, x1 = x[e2v(c)] e = x1 - x0 e = e / np.linalg.norm(e) for C in np.where(mapping == c)[0]: y0, y1 = y[E2V(C)]
from mbed.generation import make_line_mesh from mbed.meshing import embed_mesh1d import numpy as np import sys coords = np.array([[0, 0], [1, 0], [1, 1], [0, 1.]]) mesh1d = make_line_mesh(coords, close_path=True) embed_mesh1d(mesh1d, bounding_shape=0.1, how='as_lines', gmsh_args=sys.argv, save_geo='model', save_msh='model', save_embedding='test_embed_line') print() embed_mesh1d(mesh1d, bounding_shape=0.1, how='as_points', gmsh_args=sys.argv, save_geo='model', save_msh='model', niters=2, save_embedding='test_embed_point')