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
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])
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)
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])
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)
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)
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)
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)
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))
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)