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_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_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_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_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_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_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_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_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(dim): p = numpy.array([-1.0, -0.01, 0.0]) mesh = UnitSquareMesh(MPI.COMM_WORLD, 15, 15) tree = BoundingBoxTree(mesh, dim) entity, distance = compute_closest_entity(tree, p, mesh) min_distance = MPI.COMM_WORLD.allreduce(distance, op=MPI.MIN) ref_distance = numpy.sqrt(p[0]**2 + p[1]**2) 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, 0, 0]) entities = compute_collisions_point(tree, p_c) # Refine search by checking for actual collision if the entities are # cells # NOTE: Could be done for all entities if we generalize # select_colliding_cells to select_colliding_entities 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_compute_closest_entity_3d(dim): ref_distance = 0.135 p = numpy.array([0.9, 0, 1 + ref_distance]) mesh = UnitCubeMesh(MPI.COMM_WORLD, 8, 8, 8) mesh.topology.create_entities(dim) tree = BoundingBoxTree(mesh, dim) 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.9, 0, 1]) entities = compute_collisions_point(tree, p_c) # Refine search by checking for actual collision if the entities are # cells # NOTE: Could be done for all entities if we generalize # select_colliding_cells to select_colliding_entities 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 determine_closest_block(V, point): """ Determine the closest dofs (in a single block) to a point and the distance """ # Create boundingboxtree of cells connected to boundary facets tdim = V.mesh.topology.dim boundary_facets = _mesh.exterior_facet_indices(V.mesh.topology) V.mesh.topology.create_connectivity(tdim - 1, tdim) f_to_c = V.mesh.topology.connectivity(tdim - 1, tdim) boundary_cells = [] for facet in boundary_facets: boundary_cells.extend(f_to_c.links(facet)) cell_imap = V.mesh.topology.index_map(tdim) boundary_cells = np.array(np.unique(boundary_cells), dtype=np.int32) boundary_cells = boundary_cells[boundary_cells < cell_imap.size_local] bb_tree = _geometry.BoundingBoxTree(V.mesh, tdim, boundary_cells) midpoint_tree = _cpp.geometry.create_midpoint_tree(V.mesh, tdim, boundary_cells) # Find facet closest closest_cell = _geometry.compute_closest_entity( bb_tree, midpoint_tree, V.mesh, np.reshape(point, (1, 3)))[0] # Set distance high if cell is not owned if cell_imap.size_local < closest_cell or closest_cell == -1: R = 1e5 else: # Get cell geometry p = V.mesh.geometry.x entities = _cpp.mesh.entities_to_geometry(V.mesh, tdim, np.array([closest_cell], dtype=np.int32), False) R = np.linalg.norm(_cpp.geometry.compute_distance_gjk(point, p[entities[0]])) # Find processor with cell closest to point global_distances = MPI.COMM_WORLD.allgather(R) owning_processor = np.argmin(global_distances) dofmap = V.dofmap imap = dofmap.index_map ghost_owner = imap.owners local_max = imap.size_local # Determine which block of dofs is closest min_distance = max(R, 1e5) minimal_distance_block = None min_dof_owner = owning_processor if MPI.COMM_WORLD.rank == owning_processor: x = V.tabulate_dof_coordinates() cell_blocks = dofmap.cell_dofs(closest_cell) for block in cell_blocks: distance = np.linalg.norm(_cpp.geometry.compute_distance_gjk(point, x[block])) if distance < min_distance: # If cell owned by processor, but not the closest dof if block < local_max: min_dof_owner = MPI.COMM_WORLD.rank else: min_dof_owner = ghost_owner[block - local_max] minimal_distance_block = block min_distance = distance min_dof_owner = MPI.COMM_WORLD.bcast(min_dof_owner, root=owning_processor) # If dofs not owned by cell if owning_processor != min_dof_owner: owning_processor = min_dof_owner if MPI.COMM_WORLD.rank == min_dof_owner: # Re-search using the closest cell x = V.tabulate_dof_coordinates() cell_blocks = dofmap.cell_dofs(closest_cell) for block in cell_blocks: distance = np.linalg.norm(_cpp.geometry.compute_distance_gjk(point, x[block])) if distance < min_distance: # If cell owned by processor, but not the closest dof if block < local_max: min_dof_owner = MPI.COMM_WORLD.rank else: min_dof_owner = ghost_owner[block - local_max] minimal_distance_block = block min_distance = distance assert(min_dof_owner == owning_processor) return owning_processor, [minimal_distance_block] else: return owning_processor, []