def test_interpolation_matrix(cell_type, p, q): """Test discrete gradient computation with verification using Expression.""" comm = MPI.COMM_WORLD if cell_type == CellType.triangle: mesh = create_unit_square(comm, 11, 6, ghost_mode=GhostMode.none, cell_type=cell_type) family0 = "Lagrange" family1 = "Nedelec 1st kind H(curl)" elif cell_type == CellType.quadrilateral: mesh = create_unit_square(comm, 11, 6, ghost_mode=GhostMode.none, cell_type=cell_type) family0 = "Q" family1 = "RTCE" elif cell_type == CellType.hexahedron: mesh = create_unit_cube(comm, 3, 3, 2, ghost_mode=GhostMode.none, cell_type=cell_type) family0 = "Q" family1 = "NCE" elif cell_type == CellType.tetrahedron: mesh = create_unit_cube(comm, 3, 2, 2, ghost_mode=GhostMode.none, cell_type=cell_type) family0 = "Lagrange" family1 = "Nedelec 1st kind H(curl)" V = FunctionSpace(mesh, (family0, p)) W = FunctionSpace(mesh, (family1, q)) G = create_discrete_gradient(V._cpp_object, W._cpp_object) G.assemble() u = Function(V) u.interpolate(lambda x: 2 * x[0]**p + 3 * x[1]**p) grad_u = Expression(ufl.grad(u), W.element.interpolation_points) w_expr = Function(W) w_expr.interpolate(grad_u) # Compute global matrix vector product w = Function(W) G.mult(u.vector, w.vector) w.x.scatter_forward() assert np.allclose(w_expr.x.array, w.x.array)
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_save_3d_tensor(tempdir): mesh = create_unit_cube(MPI.COMM_WORLD, 8, 8, 8) u = Function(TensorFunctionSpace(mesh, ("Lagrange", 2))) u.x.array[:] = 1.0 filename = os.path.join(tempdir, "u.pvd") with VTKFile(mesh.comm, filename, "w") as vtk: vtk.write_function(u, 0.)
def test_save_vtk_mixed(tempdir): mesh = create_unit_cube(MPI.COMM_WORLD, 3, 3, 3) P2 = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 1) P1 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1) W = FunctionSpace(mesh, P2 * P1) V1 = FunctionSpace(mesh, P1) V2 = FunctionSpace(mesh, P2) U = Function(W) U.sub(0).interpolate(lambda x: np.vstack((x[0], 0.2 * x[1], np.zeros_like(x[0])))) U.sub(1).interpolate(lambda x: 0.5 * x[0]) U1, U2 = Function(V1), Function(V2) U1.interpolate(U.sub(1)) U2.interpolate(U.sub(0)) U2.name = "u" U1.name = "p" filename = os.path.join(tempdir, "u.pvd") with VTKFile(mesh.comm, filename, "w") as vtk: vtk.write_function([U2, U1], 0.) with VTKFile(mesh.comm, filename, "w") as vtk: vtk.write_function([U1, U2], 0.) Up = U.sub(1) Up.name = "psub" with pytest.raises(RuntimeError): with VTKFile(mesh.comm, filename, "w") as vtk: vtk.write_function([U2, Up, U1], 0) with pytest.raises(RuntimeError): with VTKFile(mesh.comm, filename, "w") as vtk: vtk.write_function([U.sub(i) for i in range(W.num_sub_spaces)], 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))
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 mesh_factory(tdim, n): if tdim == 1: return create_unit_interval(MPI.COMM_WORLD, n) elif tdim == 2: return create_unit_square(MPI.COMM_WORLD, n, n) elif tdim == 3: return create_unit_cube(MPI.COMM_WORLD, n, n, n)
def test_P_simplex_built_in(family, degree, cell_type, datadir): if cell_type == CellType.tetrahedron: mesh = create_unit_cube(MPI.COMM_WORLD, 5, 5, 5) elif cell_type == CellType.triangle: mesh = create_unit_square(MPI.COMM_WORLD, 5, 5) V = FunctionSpace(mesh, (family, degree)) run_scalar_test(mesh, V, degree)
def test_nedelec_spatial(order, dim): if dim == 2: mesh = create_unit_square(MPI.COMM_WORLD, 4, 4) elif dim == 3: mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2) V = FunctionSpace(mesh, ("N1curl", order)) u = Function(V) x = ufl.SpatialCoordinate(mesh) # The expression (x,y,z) is contained in the N1curl function space # order>1 f_ex = x f = Expression(f_ex, V.element.interpolation_points) u.interpolate(f) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(u - f_ex, u - f_ex) * ufl.dx))), 0) # The target expression is also contained in N2curl space of any # order V2 = FunctionSpace(mesh, ("N2curl", 1)) w = Function(V2) f2 = Expression(f_ex, V2.element.interpolation_points) w.interpolate(f2) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(w - f_ex, w - f_ex) * ufl.dx))), 0)
def test_mixed_element_vector_element_form(cell_type, sign, order): if cell_type == CellType.triangle or cell_type == CellType.quadrilateral: mesh = create_unit_square(MPI.COMM_WORLD, 2, 2, cell_type) else: mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2, cell_type) if cell_type == CellType.triangle: U_el = MixedElement([VectorElement("Lagrange", ufl.triangle, order), FiniteElement("N1curl", ufl.triangle, order)]) elif cell_type == CellType.quadrilateral: U_el = MixedElement([VectorElement("Lagrange", ufl.quadrilateral, order), FiniteElement("RTCE", ufl.quadrilateral, order)]) elif cell_type == CellType.tetrahedron: U_el = MixedElement([VectorElement("Lagrange", ufl.tetrahedron, order), FiniteElement("N1curl", ufl.tetrahedron, order)]) elif cell_type == CellType.hexahedron: U_el = MixedElement([VectorElement("Lagrange", ufl.hexahedron, order), FiniteElement("NCE", ufl.hexahedron, order)]) U = FunctionSpace(mesh, U_el) u, p = ufl.TrialFunctions(U) v, q = ufl.TestFunctions(U) f = form(inner(u, v) * ufl.dx + inner(p, q)(sign) * ufl.dS) A = dolfinx.fem.assemble_matrix(f) A.assemble() check_symmetry(A)
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 test_mixed_element_interpolation(): mesh = create_unit_cube(MPI.COMM_WORLD, 3, 3, 3) el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1) V = FunctionSpace(mesh, ufl.MixedElement([el, el])) u = Function(V) with pytest.raises(RuntimeError): u.interpolate(lambda x: np.ones(2, x.shape[1]))
def plot_streamlines(): # Plotting streamlines # ==================== # In this section we illustrate how to visualize streamlines in 3D mesh = create_unit_cube(MPI.COMM_WORLD, 4, 4, 4, CellType.hexahedron) V = VectorFunctionSpace(mesh, ("Discontinuous Lagrange", 2)) u = Function(V, dtype=np.float64) u.interpolate(lambda x: np.vstack((-(x[1] - 0.5), x[0] - 0.5, np.zeros(x.shape[1])))) cells, types, x = plot.create_vtk_mesh(V) num_dofs = x.shape[0] values = np.zeros((num_dofs, 3), dtype=np.float64) values[:, :mesh.geometry.dim] = u.x.array.reshape(num_dofs, V.dofmap.index_map_bs) # Create a point cloud of glyphs grid = pyvista.UnstructuredGrid(cells, types, x) grid["vectors"] = values grid.set_active_vectors("vectors") glyphs = grid.glyph(orient="vectors", factor=0.1) streamlines = grid.streamlines(vectors="vectors", return_source=False, source_radius=1, n_points=150) # Create Create plotter plotter = pyvista.Plotter() plotter.add_text("Streamlines.", position="upper_edge", font_size=20, color="black") plotter.add_mesh(grid, style="wireframe") plotter.add_mesh(glyphs) plotter.add_mesh(streamlines.tube(radius=0.001)) plotter.view_xy() if pyvista.OFF_SCREEN: plotter.screenshot(f"streamlines_{MPI.COMM_WORLD.rank}.png", transparent_background=transparent, window_size=[figsize, figsize]) else: plotter.show()
def mesh_factory(tdim, n, ghost_mode=GhostMode.shared_facet): if tdim == 1: return create_unit_interval(MPI.COMM_WORLD, n, ghost_mode=ghost_mode) elif tdim == 2: return create_unit_square(MPI.COMM_WORLD, n, n, ghost_mode=ghost_mode) elif tdim == 3: return create_unit_cube(MPI.COMM_WORLD, n, n, n, ghost_mode=ghost_mode)
def test_create_unit_square_hex(): mesh = create_unit_cube(MPI.COMM_WORLD, 5, 7, 9, CellType.hexahedron) assert mesh.topology.index_map(0).size_global == 480 assert mesh.topology.index_map(3).size_global == 315 assert mesh.geometry.dim == 3 assert mesh.comm.allreduce(mesh.topology.index_map(0).size_local, MPI.SUM) == 480
def generate_mesh(dim: int, simplex: bool, N: int = 3): """Helper function for parametrizing over meshes""" if dim == 2: if simplex: return create_unit_square(MPI.COMM_WORLD, N, N) else: return create_unit_square(MPI.COMM_WORLD, N, N, CellType.quadrilateral) elif dim == 3: if simplex: return create_unit_cube(MPI.COMM_WORLD, N, N, N) else: return create_unit_cube(MPI.COMM_WORLD, N, N, N, CellType.hexahedron) else: raise RuntimeError("Unsupported dimension")
def test_Refinecreate_unit_cube_repartition(): """Refine mesh of unit cube.""" mesh = create_unit_cube(MPI.COMM_WORLD, 5, 7, 9, ghost_mode=GhostMode.none) mesh.topology.create_entities(1) mesh = refine(mesh, redistribute=True) assert mesh.topology.index_map(0).size_global == 3135 assert mesh.topology.index_map(3).size_global == 15120 mesh = create_unit_cube(MPI.COMM_WORLD, 5, 7, 9, ghost_mode=GhostMode.shared_facet) mesh.topology.create_entities(1) mesh = refine(mesh, redistribute=True) assert mesh.topology.index_map(0).size_global == 3135 assert mesh.topology.index_map(3).size_global == 15120 Q = FunctionSpace(mesh, ("Lagrange", 1)) assert Q
def test_P_tp_built_in_mesh(family, degree, cell_type, datadir): if cell_type == CellType.hexahedron: mesh = create_unit_cube(MPI.COMM_WORLD, 5, 5, 5, cell_type) elif cell_type == CellType.quadrilateral: mesh = create_unit_square(MPI.COMM_WORLD, 5, 5, cell_type) mesh = get_mesh(cell_type, datadir) V = FunctionSpace(mesh, (family, degree)) run_scalar_test(mesh, V, degree)
def test_create_unit_cubeDistributed(): """Create mesh of unit cube.""" mesh = create_unit_cube(MPI.COMM_WORLD, 5, 7, 9) assert mesh.topology.index_map(0).size_global == 480 assert mesh.topology.index_map(3).size_global == 1890 assert mesh.geometry.dim == 3 assert mesh.comm.allreduce(mesh.topology.index_map(0).size_local, MPI.SUM) == 480
def test_tensor_constant(): mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2) data = [[1.0, 2.0, 1.0], [1.0, 2.0, 1.0], [1.0, 2.0, 1.0]] c0 = Constant(mesh, data) assert c0.value.shape == (3, 3) assert c0.value.all() == np.asarray(data).all() c0.value *= 2.0 assert c0.value.all() == (2.0 * np.asarray(data)).all()
def test_small_mesh(): mesh3d = create_unit_cube(MPI.COMM_WORLD, 1, 1, 1) gdim = mesh3d.geometry.dim assert mesh3d.topology.index_map(gdim).size_global == 6 mesh2d = create_unit_square(MPI.COMM_WORLD, 1, 1) gdim = mesh2d.geometry.dim assert mesh2d.topology.index_map(gdim).size_global == 2
def test_create_unit_cube_local(): """Create mesh of unit cube.""" mesh = create_unit_cube(MPI.COMM_SELF, 5, 7, 9) assert mesh.topology.index_map(0).size_global == 480 assert mesh.topology.index_map(0).size_local == 480 assert mesh.topology.index_map(3).size_global == 1890 assert mesh.topology.index_map(3).size_local == 1890 assert mesh.geometry.dim == 3
def mesh_3d(): """Create 3D mesh with regular tetrahedron and degenerate cells""" mesh3d = create_unit_cube(MPI.COMM_WORLD, 1, 1, 1) i1 = np.where((mesh3d.geometry.x == (0, 1, 0)).all(axis=1))[0][0] i2 = np.where((mesh3d.geometry.x == (1, 1, 1)).all(axis=1))[0][0] mesh3d.geometry.x[i1][0] = 1.0 mesh3d.geometry.x[i2][1] = 0.0 return mesh3d
def test_save_3d_scalar(tempdir, encoding, cell_type): filename = os.path.join(tempdir, "u3.xdmf") mesh = create_unit_cube(MPI.COMM_WORLD, 4, 3, 4, cell_type) V = FunctionSpace(mesh, ("Lagrange", 2)) u = Function(V) u.vector.set(1.0) with XDMFFile(mesh.comm, filename, "w", encoding=encoding) as file: file.write_mesh(mesh) file.write_function(u)
def test_save_3d_tensor(tempdir, encoding, cell_type): filename = os.path.join(tempdir, "u3t.xdmf") mesh = create_unit_cube(MPI.COMM_WORLD, 4, 4, 4, cell_type) u = Function(TensorFunctionSpace(mesh, ("Lagrange", 2))) u.vector.set(1.0 + ( 1j if np.issubdtype(PETSc.ScalarType, np.complexfloating) else 0)) with XDMFFile(mesh.comm, filename, "w", encoding=encoding) as file: file.write_mesh(mesh) file.write_function(u)
def test_save_3d_scalar(tempdir, cell_type): mesh = create_unit_cube(MPI.COMM_WORLD, 8, 8, 8, cell_type=cell_type) u = Function(FunctionSpace(mesh, ("Lagrange", 2))) u.x.array[:] = 1.0 filename = os.path.join(tempdir, "u.pvd") with VTKFile(MPI.COMM_WORLD, filename, "w") as vtk: vtk.write_function(u, 0.) vtk.write_function(u, 1.)
def test_scalar_constant(): mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2) c = Constant(mesh, 1.0) assert c.value.shape == () assert c.value == 1.0 c.value += 1.0 assert c.value == 2.0 c.value = 3.0 assert c.value == 3.0
def test_vector_constant(): mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2) c0 = Constant(mesh, [1.0, 2.0]) c1 = Constant(mesh, np.array([1.0, 2.0])) assert (c0.value.all() == c1.value.all()) c0.value += 1.0 assert c0.value.all() == np.array([2.0, 3.0]).all() c0.value -= [1.0, 2.0] assert c0.value[0] == c0.value[1]
def plot_nedelec(): msh = create_unit_cube(MPI.COMM_WORLD, 4, 3, 5, cell_type=CellType.tetrahedron) # We create a pyvista plotter plotter = pyvista.Plotter() plotter.add_text("Mesh and corresponding vectors", position="upper_edge", font_size=14, color="black") # Next, we create a pyvista.UnstructuredGrid based on the mesh pyvista_cells, cell_types, x = plot.create_vtk_mesh(msh, msh.topology.dim) grid = pyvista.UnstructuredGrid(pyvista_cells, cell_types, x) # Add this grid (as a wireframe) to the plotter plotter.add_mesh(grid, style="wireframe", line_width=2, color="black") # Create a function space consisting of first order Nédélec (first kind) # elements and interpolate a vector-valued expression V = FunctionSpace(msh, ("N1curl", 2)) u = Function(V, dtype=np.float64) u.interpolate(lambda x: (x[2]**2, np.zeros(x.shape[1]), -x[0] * x[2])) # Exact visualisation of the Nédélec spaces requires a Lagrange or # discontinuous Lagrange finite element functions. Therefore, we # interpolate the Nédélec function into a first-order discontinuous # Lagrange space. V0 = VectorFunctionSpace(msh, ("Discontinuous Lagrange", 2)) u0 = Function(V0, dtype=np.float64) u0.interpolate(u) # Create a second grid, whose geometry and topology is based on the # output function space cells, cell_types, x = plot.create_vtk_mesh(V0) grid = pyvista.UnstructuredGrid(cells, cell_types, x) # Create point cloud of vertices, and add the vertex values to the cloud grid.point_data["u"] = u0.x.array.reshape(x.shape[0], V0.dofmap.index_map_bs) glyphs = grid.glyph(orient="u", factor=0.1) # We add in the glyphs corresponding to the plotter plotter.add_mesh(glyphs) # Save as png if we are using a container with no rendering if pyvista.OFF_SCREEN: plotter.screenshot("3D_wireframe_with_vectors.png", transparent_background=transparent, window_size=[figsize, figsize]) else: plotter.show()
def test_ghost_3d(mode): N = 2 num_cells = N * N * N * 6 mesh = create_unit_cube(MPI.COMM_WORLD, N, N, N, ghost_mode=mode) if mesh.comm.size > 1: map = mesh.topology.index_map(3) num_cells_local = map.size_local + map.num_ghosts assert mesh.comm.allreduce(num_cells_local, op=MPI.SUM) > num_cells assert mesh.topology.index_map(0).size_global == 27 assert mesh.topology.index_map(3).size_global == num_cells