def test_compute_closest_entity_3d(dim): points = np.array([0.9, 0, 1.135]) mesh = create_unit_cube(MPI.COMM_WORLD, 8, 8, 8) mesh.topology.create_entities(dim) tree = BoundingBoxTree(mesh, dim) num_entities_local = mesh.topology.index_map(dim).size_local + mesh.topology.index_map(dim).num_ghosts entities = np.arange(num_entities_local, dtype=np.int32) midpoint_tree = create_midpoint_tree(mesh, dim, entities) closest_entities = compute_closest_entity(tree, midpoint_tree, mesh, points) # Find which entity is colliding with known closest point on mesh p_c = np.array([0.9, 0, 1]) colliding_entity_bboxes = compute_collisions(tree, p_c) # Refine search by checking for actual collision if the entities are # cells if dim == mesh.topology.dim: colliding_cells = compute_colliding_cells(mesh, colliding_entity_bboxes, p_c) if len(colliding_cells) > 0: assert np.isin(closest_entities[0], colliding_cells) else: if len(colliding_entity_bboxes.links(0)) > 0: assert np.isin(closest_entities[0], colliding_entity_bboxes.links(0))
def test_compute_closest_sub_entity(dim): """Compute distance from subset of cells in a mesh to a point inside the mesh""" ref_distance = 0.31 xc, yc, zc = 0.5, 0.5, 0.5 points = np.array([xc + ref_distance, yc, zc]) mesh = create_unit_cube(MPI.COMM_WORLD, 8, 8, 8) mesh.topology.create_entities(dim) left_entities = locate_entities(mesh, dim, lambda x: x[0] <= xc) tree = BoundingBoxTree(mesh, dim, left_entities) midpoint_tree = create_midpoint_tree(mesh, dim, left_entities) closest_entities = compute_closest_entity(tree, midpoint_tree, mesh, points) # Find which entity is colliding with known closest point on mesh p_c = np.array([xc, yc, zc]) colliding_entity_bboxes = compute_collisions(tree, p_c) # Refine search by checking for actual collision if the entities are # cells if dim == mesh.topology.dim: colliding_cells = compute_colliding_cells(mesh, colliding_entity_bboxes, p_c) if len(colliding_cells) > 0: assert np.isin(closest_entities[0], colliding_cells) else: if len(colliding_entity_bboxes.links(0)) > 0: assert np.isin(closest_entities[0], colliding_entity_bboxes.links(0))
def test_compute_closest_entity_1d(dim): ref_distance = 0.75 N = 16 points = np.array([[-ref_distance, 0, 0], [2 / N, 2 * ref_distance, 0]]) mesh = create_unit_interval(MPI.COMM_WORLD, N) tree = BoundingBoxTree(mesh, dim) num_entities_local = mesh.topology.index_map(dim).size_local + mesh.topology.index_map(dim).num_ghosts entities = np.arange(num_entities_local, dtype=np.int32) midpoint_tree = create_midpoint_tree(mesh, dim, entities) closest_entities = compute_closest_entity(tree, midpoint_tree, mesh, points) # Find which entity is colliding with known closest point on mesh p_c = np.array([[0, 0, 0], [2 / N, 0, 0]]) colliding_entity_bboxes = compute_collisions(tree, p_c) # Refine search by checking for actual collision if the entities are # cells if dim == mesh.topology.dim: colliding_cells = compute_colliding_cells(mesh, colliding_entity_bboxes, p_c) for i in range(points.shape[0]): # If colliding entity is on process if colliding_cells.links(i).size > 0: assert np.isin(closest_entities[i], colliding_cells.links(i)) else: for i in range(points.shape[0]): # Only check closest entity if any bounding box on the # process intersects with the point if colliding_entity_bboxes.links(i).size > 0: assert np.isin(closest_entities[i], colliding_entity_bboxes.links(i))
def test_eval(V, W, Q, mesh): u1 = Function(V) u2 = Function(W) u3 = Function(Q) def e2(x): values = np.empty((3, x.shape[1])) values[0] = x[0] + x[1] + x[2] values[1] = x[0] - x[1] - x[2] values[2] = x[0] + x[1] + x[2] return values def e3(x): values = np.empty((9, x.shape[1])) values[0] = x[0] + x[1] + x[2] values[1] = x[0] - x[1] - x[2] values[2] = x[0] + x[1] + x[2] values[3] = x[0] values[4] = x[1] values[5] = x[2] values[6] = -x[0] values[7] = -x[1] values[8] = -x[2] return values u1.interpolate(lambda x: x[0] + x[1] + x[2]) u2.interpolate(e2) u3.interpolate(e3) x0 = (mesh.geometry.x[0] + mesh.geometry.x[1]) / 2.0 tree = BoundingBoxTree(mesh, mesh.geometry.dim) cell_candidates = compute_collisions(tree, x0) cell = compute_colliding_cells(mesh, cell_candidates, x0) first_cell = cell[0] assert np.allclose(u3.eval(x0, first_cell)[:3], u2.eval(x0, first_cell), rtol=1e-15, atol=1e-15)
def test_compute_entity_collisions_1d(): reference = set([4]) p = numpy.array([0.3, 0.0, 0.0]) mesh = UnitIntervalMesh(MPI.COMM_WORLD, 16) tree = BoundingBoxTree(mesh, mesh.topology.dim) entities, _ = geometry.compute_entity_collisions_mesh(tree, mesh, p) assert set(entities) == reference
def test_compute_entity_collisions_3d(): reference = set([876, 877, 878, 879, 880, 881]) p = numpy.array([0.3, 0.3, 0.3]) mesh = UnitCubeMesh(MPI.comm_world, 8, 8, 8) tree = BoundingBoxTree(mesh, mesh.topology.dim) entities, _ = geometry.compute_entity_collisions_mesh(tree, mesh, p) assert set(entities) == reference
def test_compute_entity_collisions_2d(): reference = set([136, 137]) p = numpy.array([0.3, 0.3, 0.0]) mesh = UnitSquareMesh(MPI.comm_world, 16, 16) tree = BoundingBoxTree(mesh, mesh.topology.dim) entities, _ = geometry.compute_entity_collisions_mesh(tree, mesh, p) assert set(entities) == reference
def test_compute_first_entity_collision_2d(): reference = [136, 137] p = numpy.array([0.3, 0.3, 0.0]) mesh = UnitSquareMesh(MPI.comm_world, 16, 16) tree = BoundingBoxTree(mesh, mesh.topology.dim) first = geometry.compute_first_entity_collision(tree, mesh, p) assert first in reference
def test_compute_collisions_tree_1d(point, cells): mesh_A = UnitIntervalMesh(MPI.COMM_WORLD, 16) mesh_B = UnitIntervalMesh(MPI.COMM_WORLD, 16) bgeom = mesh_B.geometry.x bgeom += point tree_A = BoundingBoxTree(mesh_A, mesh_A.topology.dim) tree_B = BoundingBoxTree(mesh_B, mesh_B.topology.dim) entities = geometry.compute_collisions(tree_A, tree_B) entities_A = set([q[0] for q in entities]) entities_B = set([q[1] for q in entities]) assert entities_A == cells[0] assert entities_B == cells[1]
def test_compute_closest_sub_entity(dim): """ Compute distance from subset of cells in a mesh to a point inside the mesh """ ref_distance = 0.31 p = numpy.array([0.5 + ref_distance, 0.5, 0.5]) mesh = UnitCubeMesh(MPI.COMM_WORLD, 8, 8, 8) mesh.topology.create_entities(dim) left_entities = locate_entities(mesh, dim, lambda x: x[0] <= 0.5) tree = BoundingBoxTree(mesh, dim, left_entities) entity, distance = compute_closest_entity(tree, p, mesh) min_distance = MPI.COMM_WORLD.allreduce(distance, op=MPI.MIN) assert min_distance == pytest.approx(ref_distance, 1.0e-12) # Find which entity is colliding with known closest point on mesh p_c = numpy.array([0.5, 0.5, 0.5]) entities = compute_collisions_point(tree, p_c) # Refine search by checking for actual collision if the entities are # cells if dim == mesh.topology.dim: entities = select_colliding_cells(mesh, entities, p_c, len(entities)) if len(entities) > 0: assert numpy.isin(entity, entities)
def test_midpoint_tree(N): """ Test that midpoint tree speed up compute_closest_entity """ mesh = UnitCubeMesh(MPI.COMM_WORLD, N, N, N) mesh.topology.create_entities(mesh.topology.dim) left_cells = locate_entities(mesh, mesh.topology.dim, lambda x: x[0] <= 0.4) tree = BoundingBoxTree(mesh, mesh.topology.dim, left_cells) midpoint_tree = create_midpoint_tree(mesh, mesh.topology.dim, left_cells) p = numpy.array([1 / 3, 2 / 3, 2]) # Find entity closest to point in two steps # 1. Find closest midpoint using midpoint tree entity_m, distance_m = compute_closest_entity(midpoint_tree, p, mesh) # 2. Refine search by using exact distance query entity, distance = compute_closest_entity(tree, p, mesh, R=distance_m) # Find entity closest to point in one step e_r, d_r = compute_closest_entity(tree, p, mesh) assert entity == e_r assert distance == d_r if len(left_cells) > 0: assert distance < distance_m else: assert distance == -1 p_c = numpy.array([1 / 3, 2 / 3, 1]) entities = compute_collisions_point(tree, p_c) entities = select_colliding_cells(mesh, entities, p_c, len(entities)) if len(entities) > 0: assert numpy.isin(e_r, entities)
def test_compute_first_entity_collision_3d(): reference = [876, 877, 878, 879, 880, 881] p = numpy.array([0.3, 0.3, 0.3]) mesh = UnitCubeMesh(MPI.comm_world, 8, 8, 8) tree = BoundingBoxTree(mesh, mesh.topology.dim) first = geometry.compute_first_entity_collision(tree, mesh, p) assert first in reference
def test_sub_bbtree(): """Testing point collision with a BoundingBoxTree of sub entitites""" mesh = UnitCubeMesh(MPI.COMM_WORLD, 4, 4, 4, cell_type=cpp.mesh.CellType.hexahedron) tdim = mesh.topology.dim fdim = tdim - 1 def top_surface(x): return numpy.isclose(x[2], 1) top_facets = locate_entities_boundary(mesh, fdim, top_surface) f_to_c = mesh.topology.connectivity(tdim - 1, tdim) cells = [f_to_c.links(f)[0] for f in top_facets] bbtree = BoundingBoxTree(mesh, tdim, cells) # Compute a BBtree for all processes process_bbtree = bbtree.create_global_tree(mesh.mpi_comm()) # Find possible ranks for this point point = numpy.array([0.2, 0.2, 1.0]) ranks = compute_collisions_point(process_bbtree, point) # Compute local collisions cells = compute_collisions_point(bbtree, point) if MPI.COMM_WORLD.rank in ranks: assert len(cells) > 0 else: assert len(cells) == 0
def test_compute_first_entity_collision_1d(): reference = [4] p = numpy.array([0.3, 0, 0]) mesh = UnitIntervalMesh(MPI.comm_world, 16) tree = BoundingBoxTree(mesh, mesh.topology.dim) first = geometry.compute_first_entity_collision(tree, mesh, p) assert first in reference
def test_sub_bbtree_box(ct, N): """Test that the bounding box of the stem of the bounding box tree is what we expect""" mesh = create_unit_cube(MPI.COMM_WORLD, N, N, N, cell_type=ct) tdim = mesh.topology.dim fdim = tdim - 1 facets = locate_entities_boundary(mesh, fdim, lambda x: np.isclose(x[1], 1.0)) f_to_c = mesh.topology.connectivity(fdim, tdim) cells = np.int32(np.unique([f_to_c.links(f)[0] for f in facets])) bbtree = BoundingBoxTree(mesh, tdim, cells) num_boxes = bbtree.num_bboxes if num_boxes > 0: bbox = bbtree.get_bbox(num_boxes - 1) assert np.isclose(bbox[0][1], (N - 1) / N) tree = BoundingBoxTree(mesh, tdim) assert num_boxes < tree.num_bboxes
def test_compute_collisions_point_1d(): reference = {1: set([4])} p = numpy.array([0.3, 0, 0]) mesh = UnitIntervalMesh(MPI.COMM_WORLD, 16) for dim in range(1, 2): tree = BoundingBoxTree(mesh, mesh.topology.dim) entities = compute_collisions_point(tree, p) assert set(entities) == reference[dim]
def test_compute_first_collision_1d(): reference = {1: [4]} p = numpy.array([0.3, 0, 0]) mesh = UnitIntervalMesh(MPI.comm_world, 16) for dim in range(1, 2): tree = BoundingBoxTree(mesh, dim) first = geometry.compute_first_collision(tree, p) assert first in reference[dim]
def test_compute_closest_entity_1d(): reference = (0, 1.0) p = numpy.array([-1.0, 0, 0]) mesh = UnitIntervalMesh(MPI.COMM_WORLD, 16) tree_mid = geometry.BoundingBoxTree.create_midpoint_tree(mesh) tree = BoundingBoxTree(mesh, mesh.topology.dim) entity, distance = geometry.compute_closest_entity(tree, tree_mid, mesh, p) assert entity == reference[0] assert distance[0] == pytest.approx(reference[1], 1.0e-12)
def test_compute_closest_entity_2d(): reference = (1, 1.0) p = numpy.array([-1.0, 0.01, 0.0]) mesh = UnitSquareMesh(MPI.COMM_WORLD, 16, 16) tree_mid = create_midpoint_tree(mesh) tree = BoundingBoxTree(mesh, mesh.topology.dim) entity, distance = compute_closest_entity(tree, tree_mid, mesh, p) assert entity == reference[0] assert distance[0] == pytest.approx(reference[1], 1.0e-12)
def test_compute_closest_entity_3d(): reference = (0, 0.1) p = numpy.array([0.1, 0.05, -0.1]) mesh = UnitCubeMesh(MPI.COMM_WORLD, 8, 8, 8) tree = BoundingBoxTree(mesh, mesh.topology.dim) tree_mid = create_midpoint_tree(mesh) entity, distance = compute_closest_entity(tree, tree_mid, mesh, p) assert entity == reference[0] assert distance[0] == pytest.approx(reference[1], 1.0e-12)
def test_compute_collisions_tree_1d(point): mesh_A = UnitIntervalMesh(MPI.COMM_WORLD, 16) def locator_A(x): return x[0] >= point[0] # Locate all vertices of mesh A that should collide vertices_A = cpp.mesh.locate_entities(mesh_A, 0, locator_A) mesh_A.topology.create_connectivity(0, mesh_A.topology.dim) v_to_c = mesh_A.topology.connectivity(0, mesh_A.topology.dim) # Find all cells connected to vertex in the collision bounding box cells_A = numpy.sort( numpy.unique( numpy.hstack([v_to_c.links(vertex) for vertex in vertices_A]))) mesh_B = UnitIntervalMesh(MPI.COMM_WORLD, 16) bgeom = mesh_B.geometry.x bgeom += point def locator_B(x): return x[0] <= 1 # Locate all vertices of mesh B that should collide vertices_B = cpp.mesh.locate_entities(mesh_B, 0, locator_B) mesh_B.topology.create_connectivity(0, mesh_B.topology.dim) v_to_c = mesh_B.topology.connectivity(0, mesh_B.topology.dim) # Find all cells connected to vertex in the collision bounding box cells_B = numpy.sort( numpy.unique( numpy.hstack([v_to_c.links(vertex) for vertex in vertices_B]))) # Find colliding entities using bounding box trees tree_A = BoundingBoxTree(mesh_A, mesh_A.topology.dim) tree_B = BoundingBoxTree(mesh_B, mesh_B.topology.dim) entities = compute_collisions(tree_A, tree_B) entities_A = numpy.sort(numpy.unique([q[0] for q in entities])) entities_B = numpy.sort(numpy.unique([q[1] for q in entities])) assert numpy.allclose(entities_A, cells_A) assert numpy.allclose(entities_B, cells_B)
def test_compute_collisions_tree_3d(point): mesh_A = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2) mesh_B = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2) bgeom = mesh_B.geometry.x bgeom += point tree_A = BoundingBoxTree(mesh_A, mesh_A.topology.dim) tree_B = BoundingBoxTree(mesh_B, mesh_B.topology.dim) entities = compute_collisions(tree_A, tree_B) entities_A = np.sort(np.unique([q[0] for q in entities])) entities_B = np.sort(np.unique([q[1] for q in entities])) cells_A = find_colliding_cells(mesh_A, tree_B.get_bbox(tree_B.num_bboxes - 1)) cells_B = find_colliding_cells(mesh_B, tree_A.get_bbox(tree_A.num_bboxes - 1)) assert np.allclose(entities_A, cells_A) assert np.allclose(entities_B, cells_B)
def test_compute_collisions_tree_2d(point): mesh_A = UnitSquareMesh(MPI.COMM_WORLD, 3, 3) mesh_B = UnitSquareMesh(MPI.COMM_WORLD, 5, 5) bgeom = mesh_B.geometry.x bgeom += point tree_A = BoundingBoxTree(mesh_A, mesh_A.topology.dim) tree_B = BoundingBoxTree(mesh_B, mesh_B.topology.dim) entities = compute_collisions(tree_A, tree_B) entities_A = numpy.sort(numpy.unique([q[0] for q in entities])) entities_B = numpy.sort(numpy.unique([q[1] for q in entities])) cells_A = find_colliding_cells(mesh_A, tree_B.get_bbox(tree_B.num_bboxes - 1)) cells_B = find_colliding_cells(mesh_B, tree_A.get_bbox(tree_A.num_bboxes - 1)) assert numpy.allclose(entities_A, cells_A) assert numpy.allclose(entities_B, cells_B)
def test_compute_entity_collisions_tree_2d(): references = [[ set([20, 21, 22, 23, 28, 29, 30, 31]), set([0, 1, 2, 3, 8, 9, 10, 11]) ], [set([6]), set([25])]] points = [numpy.array([0.52, 0.51, 0.0]), numpy.array([0.9, -0.9, 0.0])] for i, point in enumerate(points): mesh_A = UnitSquareMesh(MPI.comm_world, 4, 4) mesh_B = UnitSquareMesh(MPI.comm_world, 4, 4) bgeom = mesh_B.geometry.points bgeom += point tree_A = BoundingBoxTree(mesh_A, mesh_A.topology.dim) tree_B = BoundingBoxTree(mesh_B, mesh_B.topology.dim) entities_A, entities_B = geometry.compute_entity_collisions_bb( tree_A, mesh_A, tree_B, mesh_B) assert set(entities_A) == references[i][0] assert set(entities_B) == references[i][1]
def test_surface_bbtree(): """Test creation of BBTree on subset of entities(surface cells)""" mesh = UnitCubeMesh(MPI.COMM_WORLD, 8, 8, 8) sf = cpp.mesh.exterior_facet_indices(mesh) tdim = mesh.topology.dim f_to_c = mesh.topology.connectivity(tdim - 1, tdim) cells = [f_to_c.links(f)[0] for f in sf] bbtree = BoundingBoxTree(mesh, tdim, cells) # test collision (should not collide with any) p = numpy.array([0.5, 0.5, 0.5]) assert len(compute_collisions_point(bbtree, p)) == 0
def test_surface_bbtree_collision(): """Compute collision between two meshes, where only one cell of each mesh are colliding""" tdim = 3 mesh1 = UnitCubeMesh(MPI.COMM_WORLD, 3, 3, 3, cpp.mesh.CellType.hexahedron) mesh2 = UnitCubeMesh(MPI.COMM_WORLD, 3, 3, 3, cpp.mesh.CellType.hexahedron) mesh2.geometry.x[:, :] += numpy.array([0.9, 0.9, 0.9]) sf = cpp.mesh.exterior_facet_indices(mesh1) f_to_c = mesh1.topology.connectivity(tdim - 1, tdim) # Compute unique set of cells (some will be counted multiple times) cells = list(set([f_to_c.links(f)[0] for f in sf])) bbtree1 = BoundingBoxTree(mesh1, tdim, cells) sf = cpp.mesh.exterior_facet_indices(mesh2) f_to_c = mesh2.topology.connectivity(tdim - 1, tdim) cells = list(set([f_to_c.links(f)[0] for f in sf])) bbtree2 = BoundingBoxTree(mesh2, tdim, cells) collisions = compute_collisions(bbtree1, bbtree2) assert len(collisions) == 1
def test_compute_entity_collisions_tree_3d(): references = [[ set([18, 19, 20, 21, 22, 23, 42, 43, 44, 45, 46, 47]), set([0, 1, 2, 3, 4, 5, 24, 25, 26, 27, 28, 29]) ], [set([7, 8, 30, 31, 32]), set([15, 16, 17, 39, 41])]] points = [numpy.array([0.52, 0.51, 0.3]), numpy.array([0.9, -0.9, 0.3])] for i, point in enumerate(points): mesh_A = UnitCubeMesh(MPI.comm_world, 2, 2, 2) mesh_B = UnitCubeMesh(MPI.comm_world, 2, 2, 2) bgeom = mesh_B.geometry.points bgeom += point tree_A = BoundingBoxTree(mesh_A, mesh_A.topology.dim) tree_B = BoundingBoxTree(mesh_B, mesh_B.topology.dim) entities_A, entities_B = geometry.compute_entity_collisions_bb( tree_A, mesh_A, tree_B, mesh_B) assert set(entities_A) == references[i][0] assert set(entities_B) == references[i][1]
def test_sub_bbtree_box(ct, N): """ Test that the bounding box of the stem of the bounding box tree is what we expect """ mesh = UnitCubeMesh(MPI.COMM_WORLD, N, N, N, cell_type=ct) tdim = mesh.topology.dim fdim = tdim - 1 def marker(x): return numpy.isclose(x[1], 1.0) facets = locate_entities_boundary(mesh, fdim, marker) f_to_c = mesh.topology.connectivity(fdim, tdim) cells = numpy.unique([f_to_c.links(f)[0] for f in facets]) bbtree = BoundingBoxTree(mesh, tdim, cells) num_boxes = bbtree.num_bboxes if num_boxes > 0: bbox = bbtree.get_bbox(num_boxes - 1) assert numpy.isclose(bbox[0][1], (N - 1) / N) tree = BoundingBoxTree(mesh, tdim) assert num_boxes < tree.num_bboxes
def test_midpoint_entities(): mesh = UnitSquareMesh(MPI.COMM_WORLD, 4, 4) right_cells = locate_entities(mesh, mesh.topology.dim, lambda x: 0.5 <= x[0]) tree = BoundingBoxTree(mesh, mesh.topology.dim, right_cells) midpoint_tree = create_midpoint_tree(mesh, mesh.topology.dim, right_cells) p = numpy.array([0.99, 0.95, 0]) e, R = compute_closest_entity(tree, p, mesh) e_mid, R_mid = compute_closest_entity(midpoint_tree, p, mesh) # Only check processor where point is in cell (for other procs, the # entities are not guaranteed to match) if R == 0: assert e_mid == e assert R < R_mid
def test_manifold_point_search(): # Simple two-triangle surface in 3d vertices = [(0.0, 0.0, 1.0), (1.0, 1.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0)] cells = [(0, 1, 2), (0, 1, 3)] mesh = Mesh(MPI.COMM_WORLD, CellType.triangle, numpy.array(vertices, dtype=numpy.float64), numpy.array(cells, dtype=numpy.int32), []) bb = BoundingBoxTree(mesh, mesh.topology.dim) p = numpy.array([0.5, 0.25, 0.75]) assert geometry.compute_first_entity_collision(bb, mesh, p) == 0 p = numpy.array([0.25, 0.5, 0.75]) assert geometry.compute_first_entity_collision(bb, mesh, p) == 1