Beispiel #1
0
def evaluate(points, mesh, u):
    tree = geometry.BoundingBoxTree(mesh, mesh.geometry.dim)

    num_local_cells = mesh.topology.index_map(mesh.topology.dim).size_local
    colliding_cells = -np.ones(points.shape[1], dtype=np.int32)
    for i, point in enumerate(points.T):
        # Find first colliding cell
        colliding_cell = geometry.compute_colliding_cells(tree, mesh, point, 1)
        # Only add cell to list if it is owned by the processor
        if len(colliding_cell) > 0 and colliding_cell[0] < num_local_cells:
            colliding_cells[i] = colliding_cell[0]

    local_cells = np.argwhere(colliding_cells != -1).T[0]
    on_proc = np.zeros(colliding_cells.shape[0])
    on_proc[local_cells] = 1
    # Workaround since the cell exists on multiple processors, not respecting
    # ghosting.
    num_proc = MPI.COMM_WORLD.allgather(on_proc)
    # from IPython import embed; embed()

    u_on_proc = u.eval(points.T, colliding_cells)
    u_g = MPI.COMM_WORLD.allgather(u_on_proc)
    u_gathered = sum(u_g).T[0]  #/ sum(num_proc)

    return u_gathered
Beispiel #2
0
def test_near_evaluations(R, mesh):
    # Test that we allow point evaluation that are slightly outside
    u0 = Function(R)
    u0.vector.set(1.0)

    offset = 0.99 * np.finfo(float).eps
    bb_tree = geometry.BoundingBoxTree(mesh, mesh.geometry.dim)
    a = mesh.geometry.x[0]

    cell_candidates = geometry.compute_collisions_point(bb_tree, a)
    cells = geometry.select_colliding_cells(mesh, cell_candidates, a, 1)
    a_shift_x = np.array([a[0] - offset, a[1], a[2]])

    cell_candidates = geometry.compute_collisions_point(bb_tree, a_shift_x)
    cells_shift_x = geometry.select_colliding_cells(mesh, cell_candidates,
                                                    a_shift_x, 1)

    assert u0.eval(a, cells)[0] == pytest.approx(
        u0.eval(a_shift_x, cells_shift_x)[0])

    a_shift_xyz = np.array([
        a[0] - offset / math.sqrt(3), a[1] - offset / math.sqrt(3),
        a[2] - offset / math.sqrt(3)
    ])
    cell_candidates = geometry.compute_collisions_point(bb_tree, a)
    cells_shift_xyz = geometry.select_colliding_cells(mesh, cell_candidates,
                                                      a_shift_xyz, 1)

    assert u0.eval(a, cells)[0] == pytest.approx(
        u0.eval(a_shift_xyz, cells_shift_xyz)[0])
Beispiel #3
0
def test_collision_2nd_order_triangle():
    points = np.array([[0, 0], [1, 0], [0, 1], [0.65, 0.65], [0, 0.5], [0.5, 0]])
    cells = np.array([[0, 1, 2, 3, 4, 5]])
    cell = ufl.Cell("triangle", geometric_dimension=2)
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 2))
    mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)

    # Sample points along an interior line of the domain. The last point
    # is outside the simplex made by the vertices.
    sample_points = np.array([[0.1, 0.3, 0], [0.2, 0.5, 0], [0.6, 0.6, 0]])

    # Create boundingboxtree
    tree = geometry.BoundingBoxTree(mesh, mesh.geometry.dim)
    for point in sample_points:
        colliding_cell = geometry.compute_colliding_cells(tree, mesh, point, 1)
        assert(len(colliding_cell) == 1)

    # Check if there is a point on the linear approximation of the
    # curved facet
    def line_through_points(p0, p1):
        return lambda x: (p1[1] - p0[1]) / (p1[0] - p0[0]) * (x - p0[0]) + p0[1]
    line_func = line_through_points(points[2], points[3])
    point = np.array([0.2, line_func(0.2), 0])
    # Point inside 2nd order geometry, outside linear approximation
    # Usefull for debugging on a later stage
    # point = np.array([0.25, 0.89320760, 0])
    distance = cpp.geometry.squared_distance(mesh, mesh.topology.dim - 1, 2, point)
    assert np.isclose(distance, 0)
Beispiel #4
0
def test_eval_multiple(W):
    u = Function(W)
    u.vector.set(1.0)
    mesh = W.mesh
    x0 = (mesh.geometry.x[0] + mesh.geometry.x[1]) / 2.0
    x = np.array([x0, x0 + 1.0e8])
    tree = geometry.BoundingBoxTree(mesh, W.mesh.geometry.dim)
    cells = geometry.compute_first_entity_collision(tree, mesh, x)
    u.eval(x[0], cells[0])
Beispiel #5
0
def test_manufactured_vector2(family, degree, filename, datadir):
    """Projection into H(div/curl) spaces"""

    # Skip slowest tests
    if "tetra" in filename and degree > 2:
        return

    with XDMFFile(MPI.comm_world, os.path.join(datadir, filename)) as xdmf:
        mesh = xdmf.read_mesh(GhostMode.none)

    # FIXME: these test are currently failing on unordered meshes
    if "tetra" in filename:
        if family == "N1curl":
            Ordering.order_simplex(mesh)

    V = FunctionSpace(mesh, (family, degree + 1))
    u, v = ufl.TrialFunction(V), ufl.TestFunction(V)
    a = inner(u, v) * dx

    xp = np.array([0.33, 0.33, 0.0])
    tree = geometry.BoundingBoxTree(mesh, mesh.geometry.dim)
    cells = geometry.compute_first_entity_collision(tree, mesh, xp)

    # Source term
    x = SpatialCoordinate(mesh)
    u_ref = x[0]**degree
    L = inner(u_ref, v[0]) * dx

    b = assemble_vector(L)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)

    A = assemble_matrix(a)
    A.assemble()

    # Create LU linear solver (Note: need to use a solver that
    # re-orders to handle pivots, e.g. not the PETSc built-in LU
    # solver)
    solver = PETSc.KSP().create(MPI.comm_world)
    solver.setType("preonly")
    solver.getPC().setType('lu')
    solver.setOperators(A)

    # Solve
    uh = Function(V)
    solver.solve(b, uh.vector)
    uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                          mode=PETSc.ScatterMode.FORWARD)

    up = uh.eval(xp, cells[0])
    print("test0:", up)
    print("test1:", xp[0]**degree)

    u_exact = np.zeros(mesh.geometry.dim)
    u_exact[0] = xp[0]**degree
    assert np.allclose(up, u_exact)
Beispiel #6
0
def test_eval_multiple(W):
    u = Function(W)
    u.vector.set(1.0)
    mesh = W.mesh
    x0 = (mesh.geometry.x[0] + mesh.geometry.x[1]) / 2.0
    x = np.array([x0, x0 + 1.0e8])
    tree = geometry.BoundingBoxTree(mesh, mesh.geometry.dim)
    cell_candidates = [geometry.compute_collisions_point(tree, xi) for xi in x]
    assert len(cell_candidates[1]) == 0
    cell_candidates = cell_candidates[0]
    cell = dolfinx.cpp.geometry.select_colliding_cells(mesh, cell_candidates, x0, 1)

    u.eval(x[0], cell)
Beispiel #7
0
def test_manufactured_vector1(family, degree, filename, datadir):
    """Projection into H(div/curl) spaces"""

    with XDMFFile(MPI.COMM_WORLD,
                  os.path.join(datadir, filename),
                  "r",
                  encoding=XDMFFile.Encoding.ASCII) as xdmf:
        mesh = xdmf.read_mesh(name="Grid")

    V = FunctionSpace(mesh, (family, degree))
    u, v = ufl.TrialFunction(V), ufl.TestFunction(V)
    a = inner(u, v) * dx

    # Source term
    x = SpatialCoordinate(mesh)
    u_ref = x[0]**degree
    L = inner(u_ref, v[0]) * dx

    b = assemble_vector(L)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)

    A = assemble_matrix(a)
    A.assemble()

    # Create LU linear solver (Note: need to use a solver that
    # re-orders to handle pivots, e.g. not the PETSc built-in LU
    # solver)
    solver = PETSc.KSP().create(MPI.COMM_WORLD)
    solver.setType("preonly")
    solver.getPC().setType('lu')
    solver.setOperators(A)

    # Solve
    uh = Function(V)
    solver.solve(b, uh.vector)
    uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                          mode=PETSc.ScatterMode.FORWARD)

    xp = np.array([0.33, 0.33, 0.0])
    tree = geometry.BoundingBoxTree(mesh, mesh.geometry.dim)
    cells = geometry.compute_first_entity_collision(tree, mesh, xp)

    up = uh.eval(xp, cells[0])
    print("test0:", up)
    print("test1:", xp[0]**degree)

    u_exact = np.zeros(mesh.geometry.dim)
    u_exact[0] = xp[0]**degree
    assert np.allclose(up, u_exact)
Beispiel #8
0
def test_eval(R, V, W, Q, mesh):
    u0 = Function(R)
    u1 = Function(V)
    u2 = Function(W)
    u3 = Function(Q)

    def e1(x):
        return x[0] + x[1] + x[2]

    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

    u0.vector.set(1.0)
    u1.interpolate(e1)
    u2.interpolate(e2)
    u3.interpolate(e3)

    x0 = (mesh.geometry.x[0] + mesh.geometry.x[1]) / 2.0
    tree = geometry.BoundingBoxTree(mesh, mesh.geometry.dim)
    cell_candidates = geometry.compute_collisions_point(tree, x0)
    cell = dolfinx.cpp.geometry.select_colliding_cells(mesh, cell_candidates,
                                                       x0, 1)

    assert np.allclose(u3.eval(x0, cell)[:3],
                       u2.eval(x0, cell),
                       rtol=1e-15,
                       atol=1e-15)
    with pytest.raises(ValueError):
        u0.eval([0, 0, 0, 0], 0)
    with pytest.raises(ValueError):
        u0.eval([0, 0], 0)
Beispiel #9
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, []
Ny = int(np.ceil(dim_y / wave_len * 10))

# Evaluation grid does not include absorbing layers
dim_in_x = dim_x - 2 * d_absorb
dim_in_y = dim_y - 2 * d_absorb

# Grid points
xmin, xmax, ymin, ymax = [
    -dim_in_x / 2, dim_in_x / 2, -dim_in_y / 2, dim_in_y / 2
]
plot_grid = np.mgrid[xmin:xmax:Nx * 1j, ymin:ymax:Ny * 1j]
points = np.vstack(
    (plot_grid[0].ravel(), plot_grid[1].ravel(), np.zeros(plot_grid[0].size)))

# Bounding box tree etc for function evaluations
tree = geometry.BoundingBoxTree(mesh, 2)
points_2d = points[0:2, :]
cell_candidates = [
    geometry.compute_collisions_point(tree, xi) for xi in points.T
]
cells = [
    dolfinx.cpp.geometry.select_colliding_cells(mesh, cell_candidates[i],
                                                points.T[i], 1)[0]
    for i in range(len(cell_candidates))
]

# Evaluate scattered and incident fields at grid points
u_sca = u.eval(points.T, cells).reshape((Nx, Ny))
inc_field = incident(points_2d)
u_inc = inc_field.reshape((Nx, Ny))
Beispiel #11
0
apply_lifting(b, [a_cond], bcs=[[bc]])
b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
set_bc(b, [bc])

uc = Function(U)
solver = PETSc.KSP().create(A_cond.getComm())
solver.setOperators(A_cond)
solver.solve(b, uc.vector)

# Pure displacement based formulation
a = form(- ufl.inner(sigma_u(u), ufl.grad(v)) * ufl.dx)
A = assemble_matrix(a, bcs=[bc])
A.assemble()

# Create bounding box for function evaluation
bb_tree = geometry.BoundingBoxTree(msh, 2)

# Check against standard table value
p = np.array([48.0, 52.0, 0.0], dtype=np.float64)
cell_candidates = geometry.compute_collisions(bb_tree, p)
cells = geometry.compute_colliding_cells(msh, cell_candidates, p)

uc.x.scatter_forward()
if len(cells) > 0:
    value = uc.eval(p, cells[0])
    print(value[1])
    assert np.isclose(value[1], 23.95, rtol=1.e-2)

# Check the equality of displacement based and mixed condensed global
# matrices, i.e. check that condensation is exact
assert np.isclose((A - A_cond).norm(), 0.0)