Пример #1
0
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)
Пример #2
0
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
Пример #3
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))
Пример #4
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)
Пример #5
0
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))
Пример #6
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))
Пример #7
0
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)
Пример #8
0
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)
Пример #9
0
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)
Пример #10
0
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)
Пример #11
0
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)
Пример #12
0
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, []