def make_z_mesh(num_vertices, zmin=0, zmax=1): '''{(0, 0, zmin + t*(zmax - zmin))}''' t = zmin + np.linspace(0, 1, num_vertices)*(zmax - zmin) coordinates = np.c_[np.zeros_like(t), np.zeros_like(t), t] cells = np.c_[np.arange(num_vertices - 1), np.arange(1, num_vertices)] cells.dtype = 'uintp' mesh = Mesh(mpi_comm_world()) make_mesh(coordinates, cells, 1, 3, mesh) return mesh
def dual_mesh(mesh, center='centroid', nrefs=1): ''' Dual mesh (from FVM) is triangles is obtained by dividing each triangle into 6 new ones containing cell (mid point|circumcenter) and edge midpoints. ''' # Base case if nrefs == 1: tdim, gdim = mesh.topology().dim(), mesh.geometry().dim() # Data for the mesh and mapping of old mesh vertex to cells of the dual patch coordinates, cells, mapping = dual_mesh_data(mesh, center) # Fill dmesh = make_mesh(coordinates=coordinates, cells=cells, tdim=tdim, gdim=gdim) # Attach data dmesh.parent_entity_map = {mesh.id(): mapping} return dmesh # At least 2 root_id = mesh.id() tdim = mesh.topology().dim() mesh0 = dual_mesh(mesh, center, nrefs=1) nrefs -= 1 # Root will stay the same for those are the vertices that # were originally in the mesh and only those can be traced ref_vertices, root_vertices = zip( *mesh0.parent_entity_map[mesh.id()][0].items()) while nrefs > 0: nrefs -= 1 mesh1 = dual_mesh(mesh0, center, nrefs=1) # Upda mesh1 mapping mapping0, = mesh0.parent_entity_map.values() mapping1, = mesh1.parent_entity_map.values() new_mapping = {} # New cells fall under some parent e_mapping0, e_mapping1 = mapping0[tdim], mapping1[tdim] new_mapping[tdim] = {k: e_mapping0[v] for k, v in e_mapping1.items()} # But that's not the case with vertices, we only look for root # ones in the new e_mapping1 = mapping1[0] ref_vertices = [ ref_v for ref_v, coarse_v in e_mapping1.items() if coarse_v in ref_vertices ] assert len(ref_vertices) == len(root_vertices) new_mapping[0] = dict(zip(ref_vertices, root_vertices)) mesh1.parent_entity_map = {root_id: new_mapping} mesh0 = mesh1 return mesh0
def line_mesh(branches, tol=1E-13): '''1d in 2d/3d mesh made up of branches. Branch = linked vertices''' it_branches = iter(branches) # In the mesh that we are building I want to put first the end nodes # of the branch and then the interior points of the branches as they # are visited. # Endpoints; first branch is not constrained and can add coordinates branch = next(it_branches) ext_nodes = branch[[0, -1]] ext_bounds = [(0, 1)] # For the other ones need to check collisions for branch in it_branches: endpoints = branch[[0, -1]] bounds = [] for point in endpoints: dist_f = np.linalg.norm(ext_nodes - point, 2, axis=1) f_idx = np.argmin(dist_f) # Never seen this one if dist_f[f_idx] > tol: f_idx = len(ext_nodes) ext_nodes = np.vstack([ext_nodes, point]) bounds.append(f_idx) ext_bounds.append(tuple(bounds)) cells = [] # For numbering the interior points we start with the next available fI = max(list(map(max, ext_bounds))) + 1 # Next avaiable for (fE, lE), branch in zip(ext_bounds, branches): int_nodes = branch[1:-1] if not len(int_nodes): continue # Get the node idices to encode cell connectivity lI = fI + len(int_nodes) vmap = np.r_[fE, np.arange(fI, lI), lE] # Actually add the coordinates ext_nodes = np.vstack([ext_nodes, int_nodes]) # And the cells cells.extend(list(zip(vmap[:-1], vmap[1:]))) # For next round fI = lI cells = np.array(cells, dtype='uintp').flatten() mesh = make_mesh(ext_nodes, cells, 1, ext_nodes.shape[1]) return mesh
def cross_grid_refine(mesh): ''' Cross section refine is x x / \ becomes /|\ / \ / x \ / \ / / \ \ x------x x-------x ''' x = mesh.coordinates() cells = mesh.cells() ncells, nvtx_cell = cells.shape assert any((nvtx_cell == 2, nvtx_cell == 3, nvtx_cell == 4 and mesh.topology().dim() == 3)) # Center points will be new coordinates xnew = np.mean(x[cells], axis=1) # Each cell gives rise to ... child2parent = np.empty(ncells * nvtx_cell, dtype='uintp') fine_cells = np.empty((ncells * nvtx_cell, nvtx_cell), dtype='uintp') # How we build new cells basis = map(list, combinations(range(nvtx_cell), nvtx_cell - 1)) fc, center = 0, len(x) for pc, cell in enumerate(cells): for base in basis: fine_cells[fc, :] = np.r_[cell[base], center] child2parent[fc] = pc fc += 1 center += 1 tdim = mesh.topology().dim() fine_mesh = make_mesh(np.row_stack([x, xnew]), fine_cells, tdim, mesh.geometry().dim()) fine_mesh.set_parent(mesh) mesh.set_child(fine_mesh) fine_mesh.parent_entity_map = { mesh.id(): { 0: dict(enumerate(range(mesh.num_vertices()))), tdim: dict(enumerate(child2parent)) } } return fine_mesh
u = df.Function(df.FunctionSpace(mesh, 'CG', 1)) op = Average(u, line_mesh, sq) from scipy.spatial import Delaunay from dolfin import File surface = render_avg_surface(op) nodes = np.row_stack(surface) tri = Delaunay(nodes) cells = np.fromiter(tri.simplices.flatten(), dtype='uintp').reshape(tri.simplices.shape) bounded_volume = make_mesh(nodes, cells, tdim=2, gdim=3) File('foo.pvd') << bounded_volume # for points in surface fig = plt.figure() ax = fig.add_subplot(111, projection='3d') for plane in surface: ax.plot3D(plane[:, 0], plane[:, 1], plane[:, 2], marker='o', linestyle='none') sq_integrate = lambda f, shape=sq, n=n, x0=x0: shape_integrate(
def inner_point_refine(mesh, new_pts, strict): '''' Mesh refine by adding point inside each celll x x / \ becomes /|\ / \ / x \ / \ / / \ \ x------x x-------x Strict is the rel tol for checing whether new_pts[i] is inside cell[i] ''' x = mesh.coordinates() cells = mesh.cells() ncells, nvtx_cell = cells.shape assert any((nvtx_cell == 2, nvtx_cell == 3, nvtx_cell == 4 and mesh.topology().dim() == 3)) # Center points will be new coordinates xnew = new_pts(mesh) # We have to check for duplicates #if not unique_guarantee: # pass if strict > 0: tol = mesh.hmin() * strict # The collision assert point_is_inside(xnew, x[cells], tol) # Each cell gives rise to ... child2parent = np.empty(ncells * nvtx_cell, dtype='uintp') fine_cells = np.empty((ncells * nvtx_cell, nvtx_cell), dtype='uintp') # How we build new cells basis = map(list, combinations(range(nvtx_cell), nvtx_cell - 1)) fine_coords = np.row_stack([x, xnew]) fc, center = 0, len(x) for pc, cell in enumerate(cells): for base in basis: new_cell = np.r_[cell[base], center] # Every new cell must be non-empty assert simplex_area(fine_coords[new_cell]) > 1E-15 fine_cells[fc, :] = new_cell child2parent[fc] = pc fc += 1 center += 1 tdim = mesh.topology().dim() fine_mesh = make_mesh(fine_coords, fine_cells, tdim, mesh.geometry().dim()) fine_mesh.set_parent(mesh) mesh.set_child(fine_mesh) fine_mesh.parent_entity_map = { mesh.id(): { 0: dict(enumerate(range(mesh.num_vertices()))), tdim: dict(enumerate(child2parent)) } } return fine_mesh
def inner_point_refine(mesh, new_pts, strict, nrefs=1): r''' Mesh refine by adding point inside each celll x x / \ becomes /|\ / \ / x \ / \ / / \ \ x------x x-------x Strict is the rel tol for checing whether new_pts[i] is inside cell[i] ''' if nrefs > 1: root_id = mesh.id() tdim = mesh.topology().dim() mesh0 = inner_point_refine(mesh, new_pts, strict, 1) nrefs -= 1 # Root will stay the same for those are the vertices that # were originally in the mesh and only those can be traced ref_vertices, root_vertices = zip( *mesh0.parent_entity_map[mesh.id()][0].items()) while nrefs > 0: nrefs -= 1 mesh1 = inner_point_refine(mesh0, new_pts, strict, 1) # Upda mesh1 mapping mapping0, = mesh0.parent_entity_map.values() mapping1, = mesh1.parent_entity_map.values() new_mapping = {} # New cells fall under some parent e_mapping0, e_mapping1 = mapping0[tdim], mapping1[tdim] new_mapping[tdim] = { k: e_mapping0[v] for k, v in e_mapping1.items() } # But that's not the case with vertices, we only look for root # ones in the new e_mapping1 = mapping1[0] ref_vertices = [ ref_v for ref_v, coarse_v in e_mapping1.items() if coarse_v in ref_vertices ] assert len(ref_vertices) == len(root_vertices) new_mapping[0] = dict(zip(ref_vertices, root_vertices)) mesh1.parent_entity_map = {root_id: new_mapping} mesh0 = mesh1 return mesh0 # One refinement x = mesh.coordinates() cells = mesh.cells() ncells, nvtx_cell = cells.shape assert any((nvtx_cell == 2, nvtx_cell == 3, nvtx_cell == 4 and mesh.topology().dim() == 3)) # Center points will be new coordinates xnew = new_pts(mesh) # We have to check for duplicates #if not unique_guarantee: # pass if strict > 0: tol = mesh.hmin() * strict # The collision assert point_is_inside(xnew, x[cells], tol) # Each cell gives rise to ... child2parent = np.empty(ncells * nvtx_cell, dtype='uintp') fine_cells = np.empty((ncells * nvtx_cell, nvtx_cell), dtype='uintp') # How we build new cells basis = list(map(list, combinations(list(range(nvtx_cell)), nvtx_cell - 1))) fine_coords = np.row_stack([x, xnew]) fc, center = 0, len(x) for pc, cell in enumerate(cells): for base in basis: new_cell = np.r_[cell[base], center] # Every new cell must be non-empty assert simplex_area(fine_coords[new_cell]) > 1E-15 fine_cells[fc, :] = new_cell child2parent[fc] = pc fc += 1 center += 1 tdim = mesh.topology().dim() fine_mesh = make_mesh(fine_coords, fine_cells, tdim, mesh.geometry().dim()) fine_mesh.parent_entity_map = { mesh.id(): { 0: dict(enumerate(range(mesh.num_vertices()))), tdim: dict(enumerate(child2parent)) } } return fine_mesh