def test_3d(tempdir, cell_type, encoding): filename = os.path.join(tempdir, "meshtags_3d.xdmf") comm = MPI.COMM_WORLD mesh = UnitCubeMesh(comm, 4, 4, 4, cell_type) bottom_facets = locate_entities(mesh, 2, lambda x: np.isclose(x[1], 0.0)) bottom_values = np.full(bottom_facets.shape, 1, dtype=np.intc) left_facets = locate_entities(mesh, 2, lambda x: np.isclose(x[0], 0.0)) left_values = np.full(left_facets.shape, 2, dtype=np.intc) indices, pos = np.unique(np.hstack((bottom_facets, left_facets)), return_index=True) mt = MeshTags(mesh, 2, indices, np.hstack((bottom_values, left_values))[pos]) mt.name = "facets" top_lines = locate_entities(mesh, 1, lambda x: np.isclose(x[2], 1.0)) top_values = np.full(top_lines.shape, 3, dtype=np.intc) right_lines = locate_entities(mesh, 1, lambda x: np.isclose(x[0], 1.0)) right_values = np.full(right_lines.shape, 4, dtype=np.intc) indices, pos = np.unique(np.hstack((top_lines, right_lines)), return_index=True) mt_lines = MeshTags(mesh, 1, indices, np.hstack((top_values, right_values))[pos]) mt_lines.name = "lines" with XDMFFile(comm, filename, "w", encoding=encoding) as file: mesh.topology.create_connectivity_all() file.write_mesh(mesh) file.write_meshtags(mt) file.write_meshtags(mt_lines) file.write_information("units", "mm") with XDMFFile(comm, filename, "r", encoding=encoding) as file: mesh_in = file.read_mesh() mesh_in.topology.create_connectivity_all() mt_in = file.read_meshtags(mesh_in, "facets") mt_lines_in = file.read_meshtags(mesh_in, "lines") units = file.read_information("units") assert units == "mm" assert mt_in.name == "facets" assert mt_lines_in.name == "lines" with XDMFFile(comm, os.path.join(tempdir, "meshtags_3d_out.xdmf"), "w", encoding=encoding) as file: file.write_mesh(mesh_in) file.write_meshtags(mt_lines_in) file.write_meshtags(mt_in) # Check number of owned and marked entities lines_local = comm.allreduce((mt_lines.indices < mesh.topology.index_map(1).size_local).sum(), op=MPI.SUM) lines_local_in = comm.allreduce( (mt_lines_in.indices < mesh_in.topology.index_map(1).size_local).sum(), op=MPI.SUM) assert lines_local == lines_local_in # Check that only owned data is written to file facets_local = comm.allreduce((mt.indices < mesh.topology.index_map(2).size_local).sum(), op=MPI.SUM) parser = ElementTree.XMLParser() tree = ElementTree.parse(os.path.join(tempdir, "meshtags_3d_out.xdmf"), parser) num_lines = int(tree.findall(".//Grid[@Name='lines']/Topology")[0].get("NumberOfElements")) num_facets = int(tree.findall(".//Grid[@Name='facets']/Topology")[0].get("NumberOfElements")) assert(num_lines == lines_local) assert(num_facets == facets_local)
def test_3d(tempdir, cell_type, encoding): filename = os.path.join(tempdir, "meshtags_3d.xdmf") comm = MPI.COMM_WORLD mesh = UnitCubeMesh(comm, 4, 4, 4, cell_type) bottom_facets = locate_entities(mesh, 2, lambda x: np.isclose(x[1], 0.0)) bottom_values = np.full(bottom_facets.shape, 1, dtype=np.intc) left_facets = locate_entities(mesh, 2, lambda x: np.isclose(x[0], 0.0)) left_values = np.full(left_facets.shape, 2, dtype=np.intc) indices, pos = np.unique(np.hstack((bottom_facets, left_facets)), return_index=True) mt = MeshTags(mesh, 2, indices, np.hstack((bottom_values, left_values))[pos]) mt.name = "facets" top_lines = locate_entities(mesh, 1, lambda x: np.isclose(x[2], 1.0)) top_values = np.full(top_lines.shape, 3, dtype=np.intc) right_lines = locate_entities(mesh, 1, lambda x: np.isclose(x[0], 1.0)) right_values = np.full(right_lines.shape, 4, dtype=np.intc) indices, pos = np.unique(np.hstack((top_lines, right_lines)), return_index=True) mt_lines = MeshTags(mesh, 1, indices, np.hstack((top_values, right_values))[pos]) mt_lines.name = "lines" with XDMFFile(comm, filename, "w", encoding=encoding) as file: mesh.topology.create_connectivity_all() file.write_mesh(mesh) file.write_meshtags(mt) file.write_meshtags(mt_lines) with XDMFFile(comm, filename, "r", encoding=encoding) as file: mesh_in = file.read_mesh() mesh_in.topology.create_connectivity_all() mt_in = file.read_meshtags(mesh_in, "facets") mt_lines_in = file.read_meshtags(mesh_in, "lines") assert mt_in.name == "facets" assert mt_lines_in.name == "lines" with XDMFFile(comm, os.path.join(tempdir, "meshtags_3d_out.xdmf"), "w", encoding=encoding) as file: file.write_mesh(mesh_in) file.write_meshtags(mt_lines_in) file.write_meshtags(mt_in) # Check number of owned and marked entities lines_local = comm.allreduce((mt_lines.indices < mesh.topology.index_map(1).size_local).sum(), op=MPI.SUM) lines_local_in = comm.allreduce( (mt_lines_in.indices < mesh_in.topology.index_map(1).size_local).sum(), op=MPI.SUM) assert lines_local == lines_local_in
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_submesh_cell_assembly(d, n, k, space, ghost_mode): """Check that assembling a form over a unit square gives the same result as assembling over half of a 2x1 rectangle with the same triangulation.""" if d == 2: mesh_0 = create_unit_square( MPI.COMM_WORLD, n, n, ghost_mode=ghost_mode) mesh_1 = create_rectangle( MPI.COMM_WORLD, ((0.0, 0.0), (2.0, 1.0)), (2 * n, n), ghost_mode=ghost_mode) else: mesh_0 = create_unit_cube( MPI.COMM_WORLD, n, n, n, ghost_mode=ghost_mode) mesh_1 = create_box( MPI.COMM_WORLD, ((0.0, 0.0, 0.0), (2.0, 1.0, 1.0)), (2 * n, n, n), ghost_mode=ghost_mode) A_mesh_0 = assemble(mesh_0, space, k) edim = mesh_1.topology.dim entities = locate_entities(mesh_1, edim, lambda x: x[0] <= 1.0) submesh = create_submesh(mesh_1, edim, entities)[0] A_submesh = assemble(submesh, space, k) # FIXME Would probably be better to compare entries rather than just # norms assert(np.isclose(A_mesh_0.norm(), A_submesh.norm()))
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_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_refine_from_cells(): """Check user interface for using local cells to define edges""" Nx = 8 Ny = 3 assert Nx % 2 == 0 mesh = create_unit_square(MPI.COMM_WORLD, Nx, Ny, diagonal=DiagonalType.left, ghost_mode=GhostMode.none) mesh.topology.create_entities(1) def left_side(x, tol=1e-16): return x[0] <= 0.5 + tol cells = locate_entities(mesh, mesh.topology.dim, left_side) if MPI.COMM_WORLD.size == 0: assert cells.__len__() == Nx * Ny edges = compute_incident_entities(mesh, cells, 2, 1) if MPI.COMM_WORLD.size == 0: assert edges.__len__() == Nx // 2 * (2 * Ny + 1) + (Nx // 2 + 1) * Ny mesh2 = refine(mesh, edges, redistribute=True) num_cells_global = mesh2.topology.index_map(2).size_global actual_cells = 3 * (Nx * Ny) + 3 * Ny + 2 * Nx * Ny assert num_cells_global == actual_cells
def test_interpolate_subset(order, dim, affine): if dim == 2: ct = CellType.triangle if affine else CellType.quadrilateral mesh = create_unit_square(MPI.COMM_WORLD, 3, 4, ct) elif dim == 3: ct = CellType.tetrahedron if affine else CellType.hexahedron mesh = create_unit_cube(MPI.COMM_WORLD, 3, 2, 2, ct) V = FunctionSpace(mesh, ("DG", order)) u = Function(V) cells = locate_entities(mesh, mesh.topology.dim, lambda x: x[1] <= 0.5 + 1e-10) num_local_cells = mesh.topology.index_map(mesh.topology.dim).size_local cells_local = cells[cells < num_local_cells] x = ufl.SpatialCoordinate(mesh) f = x[1]**order expr = Expression(f, V.element.interpolation_points) u.interpolate(expr, cells_local) mt = MeshTags(mesh, mesh.topology.dim, cells_local, np.ones(cells_local.size, dtype=np.int32)) dx = ufl.Measure("dx", domain=mesh, subdomain_data=mt) assert np.isclose( np.abs(form(assemble_scalar(form(ufl.inner(u - f, u - f) * dx(1))))), 0) integral = mesh.comm.allreduce(assemble_scalar(form(u * dx)), op=MPI.SUM) assert np.isclose(integral, 1 / (order + 1) * 0.5**(order + 1), 0)
def xtest_submesh(tempdir, d, n, codim, ghost_mode, encoding): mesh = mesh_factory(d, n, ghost_mode) edim = d - codim entities = locate_entities(mesh, edim, lambda x: x[0] >= 0.5) submesh = create_submesh(mesh, edim, entities)[0] filename = os.path.join(tempdir, "submesh.xdmf") # Check writing the mesh doesn't cause a segmentation fault with XDMFFile(mesh.comm, filename, "w", encoding=encoding) as xdmf: xdmf.write_mesh(submesh)
def test_submesh(d, n, codim, marker, ghost_mode): if d == 2: mesh = create_unit_square(MPI.COMM_WORLD, n, n, ghost_mode=ghost_mode) else: mesh = create_unit_cube(MPI.COMM_WORLD, n, n, n, ghost_mode=ghost_mode) edim = mesh.topology.dim - codim entities = locate_entities(mesh, edim, marker) submesh, vertex_map, geom_map = create_submesh(mesh, edim, entities) submesh_topology_test(mesh, submesh, vertex_map, edim, entities) submesh_geometry_test(mesh, submesh, geom_map, edim, entities)
def test_create(cell_type): comm = MPI.COMM_WORLD mesh = create_unit_cube(comm, 6, 6, 6, cell_type) marked_lines = locate_entities(mesh, 1, lambda x: np.isclose(x[1], 0.5)) f_v = mesh.topology.connectivity(1, 0).array.reshape(-1, 2) entities = create_adjacencylist(f_v[marked_lines]) values = np.full(marked_lines.shape[0], 2, dtype=np.int32) mt = create_meshtags(mesh, 1, entities, values) assert mt.indices.shape == marked_lines.shape
def test_create(cell_type): comm = MPI.COMM_WORLD mesh = UnitCubeMesh(comm, 6, 6, 6, cell_type) mesh.topology.create_connectivity_all() marked_lines = locate_entities(mesh, 1, lambda x: numpy.isclose(x[1], 0.5)) f_v = mesh.topology.connectivity(1, 0).array().reshape(-1, 2) entities = cpp.graph.AdjacencyList_int32(f_v[marked_lines]) values = numpy.full(marked_lines.shape[0], 2, dtype=numpy.int32) mt = create_meshtags(mesh, 1, entities, values) assert mt.indices.shape == marked_lines.shape
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_ufl_id(): """Test that UFL can process MeshTags (tests ufl_id attribute)""" comm = MPI.COMM_WORLD mesh = create_unit_cube(comm, 6, 6, 6) tdim = mesh.topology.dim marked_facets = locate_entities(mesh, tdim - 1, lambda x: np.isclose(x[1], 1)) f_v = mesh.topology.connectivity(tdim - 1, 0).array.reshape(-1, 3) entities = create_adjacencylist(f_v[marked_facets]) values = np.full(marked_facets.shape[0], 2, dtype=np.int32) ft = meshtags_from_entities(mesh, tdim - 1, entities, values) ds = Measure("ds", domain=mesh, subdomain_data=ft, subdomain_id=(2, 3)) a = 1 * ds assert isinstance(a.subdomain_data(), dict)
np.isclose(x[2], zdim - beta * zdim)) def left_support(x): return np.logical_and(np.isclose(x[1], 0.0), np.isclose(x[2], left_support_margin)) def top_load(x): return np.isclose(x[1], ydim) left_support_lines = locate_entities_boundary(mesh, 1, left_support) right_support_lines = locate_entities_boundary(mesh, 1, right_support) top_load_facets = locate_entities_boundary(mesh, 2, top_load) replaced_part_cells = locate_entities( mesh, 3, lambda x: np.greater_equal(x[2], zdim - alpha * zdim)) replaced_part_interface = locate_entities( mesh, 2, lambda x: np.isclose(x[2], zdim - alpha * zdim)) right_side_facets = locate_entities_boundary(mesh, 2, lambda x: np.isclose(x[2], zdim)) mt_top_load = MeshTags(mesh, 2, top_load_facets, 1) # External boundary facets ds = ufl.Measure("ds", domain=mesh, subdomain_data=mt_top_load, metadata={"quadrature_degree": 2}) dx = ufl.Measure("dx", domain=mesh, subdomain_data=mt_cell,
def test_coupled_poisson(): # dS integrals in parallel require shared_facet ghost mode if MPI.COMM_WORLD.size == 1: ghost_mode = dolfinx.cpp.mesh.GhostMode.none else: ghost_mode = dolfinx.cpp.mesh.GhostMode.shared_facet mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, 16, 16, ghost_mode=ghost_mode) mesh.topology.create_connectivity_all() left_half = locate_entities(mesh, mesh.topology.dim, lambda x: numpy.less_equal(x[0], 0.5)) right_half = locate_entities(mesh, mesh.topology.dim, lambda x: numpy.greater_equal(x[0], 0.5)) left_values = numpy.full(left_half.shape, 1, dtype=numpy.intc) right_values = numpy.full(right_half.shape, 2, dtype=numpy.intc) indices = numpy.hstack((left_half, right_half)) values = numpy.hstack((left_values, right_values)) indices, pos = numpy.unique(indices, return_index=True) mt = dolfinx.mesh.MeshTags(mesh, mesh.topology.dim, indices, values[pos]) interface_facets = dolfinx.mesh.locate_entities( mesh, mesh.topology.dim - 1, lambda x: numpy.isclose(x[0], 0.5)) indices = numpy.unique(interface_facets) mt_interface = dolfinx.mesh.MeshTags(mesh, mesh.topology.dim - 1, indices, 1) U0 = dolfinx.FunctionSpace(mesh, ("P", 1)) U1 = dolfinx.FunctionSpace(mesh, ("P", 2)) L = dolfinx.FunctionSpace(mesh, ("P", 1)) v0 = ufl.TestFunction(U0) v1 = ufl.TestFunction(U1) m = ufl.TestFunction(L) u0_bc = dolfinx.Function(U0) u1_bc = dolfinx.Function(U1) dx = ufl.Measure("dx", subdomain_data=mt, domain=mesh) dS = ufl.Measure("dS", subdomain_data=mt_interface, domain=mesh) w0 = dolfinx.Function(U0, name="w0") w1 = dolfinx.Function(U1, name="w1") lam = dolfinx.Function(L, name="l") b0 = v0 * dx(1) b1 = v1 * dx(2) b2 = dolfinx.Function(L)("+") * m("+") * dS(1) F0 = ufl.inner(ufl.grad(w0), ufl.grad(v0)) * dx(1) + lam("-") * v0("-") * dS(1) - b0 F1 = ufl.inner(ufl.grad(w1), ufl.grad(v1)) * dx(2) - lam("+") * v1("+") * dS(1) - b1 F2 = w0("-") * m("-") * dS(1) - w1("+") * m("+") * dS(1) - b2 bcdofsU0 = dolfinx.fem.locate_dofs_geometrical(U0, lambda x: numpy.isclose(x[0], 0.0)) bcdofsU1 = dolfinx.fem.locate_dofs_geometrical(U1, lambda x: numpy.isclose(x[0], 1.0)) bcs = [dolfinx.fem.DirichletBC(u0_bc, bcdofsU0), dolfinx.fem.DirichletBC(u1_bc, bcdofsU1)] rdofsU0 = dolfinx.fem.locate_dofs_topological(U0, mesh.topology.dim, left_half, remote=False)[:, 0] rdofsU1 = dolfinx.fem.locate_dofs_topological(U1, mesh.topology.dim, right_half, remote=False)[:, 0] rdofsL = dolfinx.fem.locate_dofs_topological(L, mesh.topology.dim - 1, interface_facets, remote=False)[:, 0] r = dolfiny.restriction.Restriction([U0, U1, L], [rdofsU0, rdofsU1, rdofsL]) opts = PETSc.Options("poisson") opts["snes_type"] = "newtonls" opts["snes_linesearch_type"] = "basic" opts["snes_rtol"] = 1.0e-08 opts["snes_max_it"] = 5 opts["ksp_type"] = "preonly" opts["pc_type"] = "lu" opts["pc_factor_mat_solver_type"] = "mumps" opts_glob = PETSc.Options() opts_glob['mat_mumps_icntl_24'] = 1 problem = dolfiny.snesblockproblem.SNESBlockProblem( [F0, F1, F2], [w0, w1, lam], bcs=bcs, restriction=r, prefix="poisson") s0, s1, s2 = problem.solve() assert problem.snes.getConvergedReason() > 0 assert problem.snes.getIterationNumber() == 1 # Evaluate the solution -0.5*x*(x-1) at x=0.5 bb_tree = dolfinx.cpp.geometry.BoundingBoxTree(mesh, 2) p = numpy.array([0.5, 0.5, 0.0], dtype=numpy.float64) cell_candidates = dolfinx.cpp.geometry.compute_collisions_point(bb_tree, p) cell = dolfinx.cpp.geometry.select_colliding_cells(mesh, cell_candidates, p, 1) if len(cell) > 0: value_s0 = s0.eval(p, cell) value_s1 = s1.eval(p, cell) assert(numpy.isclose(value_s0[0], 0.125, rtol=1.0e-4)) assert(numpy.isclose(value_s1[0], 0.125, rtol=1.0e-4))
from mpi4py import MPI from petsc4py.PETSc import ScalarType # Create a mesh. For what comes later in this demo we need to ensure # that a boundary between cells is located at x0=0.5 msh = create_rectangle(MPI.COMM_WORLD, ((0.0, 0.0), (1.0, 1.0)), (16, 16), CellType.triangle) # Create Nedelec function space and finite element Function V = FunctionSpace(msh, ("Nedelec 1st kind H(curl)", 1)) u = Function(V, dtype=ScalarType) # Find cells with *all* vertices (0) <= 0.5 or (1) >= 0.5 tdim = msh.topology.dim cells0 = locate_entities(msh, tdim, lambda x: x[0] <= 0.5) cells1 = locate_entities(msh, tdim, lambda x: x[0] >= 0.5) # Interpolate in the Nedelec/H(curl) space a vector-valued expression # ``f``, where f \dot e_0 is discontinuous at x0 = 0.5 and f \dot e_1 # is continuous. u.interpolate(lambda x: np.vstack((x[0], x[1])), cells0) u.interpolate(lambda x: np.vstack((x[0] + 1, x[1])), cells1) # Create a vector-valued discontinuous Lagrange space and function, and # interpolate the H(curl) function `u` V0 = VectorFunctionSpace(msh, ("Discontinuous Lagrange", 1)) u0 = Function(V0, dtype=ScalarType) u0.interpolate(u) try: