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 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 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 test_assemble_derivatives(): """This test checks the original_coefficient_positions, which may change under differentiation (some coefficients and constants are eliminated)""" mesh = create_unit_square(MPI.COMM_WORLD, 12, 12) Q = FunctionSpace(mesh, ("Lagrange", 1)) u = Function(Q) v = ufl.TestFunction(Q) du = ufl.TrialFunction(Q) b = Function(Q) c1 = Constant(mesh, np.array([[1.0, 0.0], [3.0, 4.0]], PETSc.ScalarType)) c2 = Constant(mesh, PETSc.ScalarType(2.0)) b.x.array[:] = 2.0 # derivative eliminates 'u' and 'c1' L = ufl.inner(c1, c1) * v * dx + c2 * b * inner(u, v) * dx a = form(derivative(L, u, du)) A1 = assemble_matrix(a) A1.assemble() a = form(c2 * b * inner(du, v) * dx) A2 = assemble_matrix(a) A2.assemble() assert (A1 - A2).norm() == pytest.approx(0.0, rel=1e-12, abs=1e-12)
def run_vector_test(V, poly_order): """Test that interpolation is correct in a scalar valued space.""" random.seed(12) tdim = V.mesh.topology.dim if tdim == 1: def f(x): return x[0]**poly_order elif tdim == 2: def f(x): return (x[1]**min(poly_order, 1), 2 * x[0]**poly_order) else: def f(x): return (x[1]**min(poly_order, 1), 2 * x[0]**poly_order, 3 * x[2]**min(poly_order, 2)) v = Function(V) v.interpolate(f) points = [random_point_in_cell(V.mesh) for count in range(5)] cells = [0 for count in range(5)] values = v.eval(points, cells) for p, val in zip(points, values): assert np.allclose(val, f(p))
def test_copy(V): u = Function(V) u.interpolate(lambda x: x[0] + 2 * x[1]) v = u.copy() assert np.allclose(u.x.array, v.x.array) u.x.array[:] = 1 assert not np.allclose(u.x.array, v.x.array)
def test_additivity(mode): mesh = create_unit_square(MPI.COMM_WORLD, 12, 12, ghost_mode=mode) V = FunctionSpace(mesh, ("Lagrange", 1)) f1 = Function(V) f2 = Function(V) f3 = Function(V) f1.x.array[:] = 1.0 f2.x.array[:] = 2.0 f3.x.array[:] = 3.0 j1 = ufl.inner(f1, f1) * ufl.dx(mesh) j2 = ufl.inner(f2, f2) * ufl.ds(mesh) j3 = ufl.inner(ufl.avg(f3), ufl.avg(f3)) * ufl.dS(mesh) # Assemble each scalar form separately J1 = mesh.comm.allreduce(assemble_scalar(form(j1)), op=MPI.SUM) J2 = mesh.comm.allreduce(assemble_scalar(form(j2)), op=MPI.SUM) J3 = mesh.comm.allreduce(assemble_scalar(form(j3)), op=MPI.SUM) # Sum forms and assemble the result J12 = mesh.comm.allreduce(assemble_scalar(form(j1 + j2)), op=MPI.SUM) J13 = mesh.comm.allreduce(assemble_scalar(form(j1 + j3)), op=MPI.SUM) J23 = mesh.comm.allreduce(assemble_scalar(form(j2 + j3)), op=MPI.SUM) J123 = mesh.comm.allreduce(assemble_scalar(form(j1 + j2 + j3)), op=MPI.SUM) # Compare assembled values assert (J1 + J2) == pytest.approx(J12) assert (J1 + J3) == pytest.approx(J13) assert (J2 + J3) == pytest.approx(J23) assert (J1 + J2 + J3) == pytest.approx(J123)
def test_scatter_forward(element): mesh = create_unit_square(MPI.COMM_WORLD, 5, 5) V = FunctionSpace(mesh, element) u = Function(V) bs = V.dofmap.bs u.interpolate(lambda x: [x[i] for i in range(bs)]) # Forward scatter should have no effect w0 = u.x.array.copy() u.x.scatter_forward() assert np.allclose(w0, u.x.array) # Fill local array with the mpi rank u.x.array.fill(MPI.COMM_WORLD.rank) w0 = u.x.array.copy() u.x.scatter_forward() # Now the ghosts should have the value of the rank of # the owning process ghost_owners = u.function_space.dofmap.index_map.ghost_owner_rank() ghost_owners = np.repeat(ghost_owners, bs) local_size = u.function_space.dofmap.index_map.size_local * bs assert np.allclose(u.x.array[local_size:], ghost_owners)
def test_scatter_reverse(element): comm = MPI.COMM_WORLD mesh = create_unit_square(MPI.COMM_WORLD, 5, 5) V = FunctionSpace(mesh, element) u = Function(V) bs = V.dofmap.bs u.interpolate(lambda x: [x[i] for i in range(bs)]) # Reverse scatter (insert) should have no effect w0 = u.x.array.copy() u.x.scatter_reverse(_cpp.common.ScatterMode.insert) assert np.allclose(w0, u.x.array) # Fill with MPI rank, and sum all entries in the vector (including ghosts) u.x.array.fill(comm.rank) all_count0 = MPI.COMM_WORLD.allreduce(u.x.array.sum(), op=MPI.SUM) # Reverse scatter (add) u.x.scatter_reverse(_cpp.common.ScatterMode.add) num_ghosts = V.dofmap.index_map.num_ghosts ghost_count = MPI.COMM_WORLD.allreduce(num_ghosts * comm.rank, op=MPI.SUM) # New count should have gone up by the number of ghosts times their rank # on all processes all_count1 = MPI.COMM_WORLD.allreduce(u.x.array.sum(), op=MPI.SUM) assert all_count1 == (all_count0 + bs * ghost_count)
def test_constant_bc(mesh_factory): """Test that setting a dirichletbc with a constant yields the same result as setting it with a function""" func, args = mesh_factory mesh = func(*args) V = FunctionSpace(mesh, ("Lagrange", 1)) c = PETSc.ScalarType(2) tdim = mesh.topology.dim boundary_facets = locate_entities_boundary( mesh, tdim - 1, lambda x: np.ones(x.shape[1], dtype=bool)) boundary_dofs = locate_dofs_topological(V, tdim - 1, boundary_facets) u_bc = Function(V) u_bc.x.array[:] = c bc_f = dirichletbc(u_bc, boundary_dofs) bc_c = dirichletbc(c, boundary_dofs, V) u_f = Function(V) set_bc(u_f.vector, [bc_f]) u_c = Function(V) set_bc(u_c.vector, [bc_c]) assert np.allclose(u_f.vector.array, u_c.vector.array)
def test_vector_constant_bc(mesh_factory): """Test that setting a dirichletbc with a vector valued constant yields the same result as setting it with a function""" func, args = mesh_factory mesh = func(*args) tdim = mesh.topology.dim V = VectorFunctionSpace(mesh, ("Lagrange", 1)) assert V.num_sub_spaces == mesh.geometry.dim c = np.arange(1, mesh.geometry.dim + 1, dtype=PETSc.ScalarType) boundary_facets = locate_entities_boundary( mesh, tdim - 1, lambda x: np.ones(x.shape[1], dtype=bool)) # Set using sub-functions Vs = [V.sub(i).collapse()[0] for i in range(V.num_sub_spaces)] boundary_dofs = [ locate_dofs_topological((V.sub(i), Vs[i]), tdim - 1, boundary_facets) for i in range(len(Vs)) ] u_bcs = [Function(Vs[i]) for i in range(len(Vs))] bcs_f = [] for i, u in enumerate(u_bcs): u_bcs[i].x.array[:] = c[i] bcs_f.append(dirichletbc(u_bcs[i], boundary_dofs[i], V.sub(i))) u_f = Function(V) set_bc(u_f.vector, bcs_f) # Set using constant boundary_dofs = locate_dofs_topological(V, tdim - 1, boundary_facets) bc_c = dirichletbc(c, boundary_dofs, V) u_c = Function(V) u_c.x.array[:] = 0.0 set_bc(u_c.vector, [bc_c]) assert np.allclose(u_f.x.array, u_c.x.array)
def test_save_1d_scalar(tempdir): mesh = create_unit_interval(MPI.COMM_WORLD, 32) u = Function(FunctionSpace(mesh, ("Lagrange", 2))) u.interpolate(lambda x: x[0]) filename = os.path.join(tempdir, "u.pvd") with VTKFile(MPI.COMM_WORLD, filename, "w") as vtk: vtk.write_function(u, 0.)
def test_sub_constant_bc(mesh_factory): """Test that setting a dirichletbc with on a component of a vector valued function yields the same result as setting it with a function""" func, args = mesh_factory mesh = func(*args) tdim = mesh.topology.dim V = VectorFunctionSpace(mesh, ("Lagrange", 1)) c = Constant(mesh, PETSc.ScalarType(3.14)) boundary_facets = locate_entities_boundary( mesh, tdim - 1, lambda x: np.ones(x.shape[1], dtype=bool)) for i in range(V.num_sub_spaces): Vi = V.sub(i).collapse()[0] u_bci = Function(Vi) u_bci.x.array[:] = PETSc.ScalarType(c.value) boundary_dofsi = locate_dofs_topological((V.sub(i), Vi), tdim - 1, boundary_facets) bc_fi = dirichletbc(u_bci, boundary_dofsi, V.sub(i)) boundary_dofs = locate_dofs_topological(V.sub(i), tdim - 1, boundary_facets) bc_c = dirichletbc(c, boundary_dofs, V.sub(i)) u_f = Function(V) set_bc(u_f.vector, [bc_fi]) u_c = Function(V) set_bc(u_c.vector, [bc_c]) assert np.allclose(u_f.vector.array, u_c.vector.array)
def monolithic_solve(): """Monolithic (interleaved) solver""" P2_el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2) P1_el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1) TH = P2_el * P1_el W = FunctionSpace(mesh, TH) (u, p) = ufl.TrialFunctions(W) (v, q) = ufl.TestFunctions(W) a00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx a01 = ufl.inner(p, ufl.div(v)) * dx a10 = ufl.inner(ufl.div(u), q) * dx a = a00 + a01 + a10 p00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx p11 = ufl.inner(p, q) * dx p_form = p00 + p11 f = Function(W.sub(0).collapse()[0]) p_zero = Function(W.sub(1).collapse()[0]) L0 = inner(f, v) * dx L1 = inner(p_zero, q) * dx L = L0 + L1 a, p_form, L = form(a), form(p_form), form(L) bdofsW0_P2_0 = locate_dofs_topological(W.sub(0), facetdim, bndry_facets0) bdofsW0_P2_1 = locate_dofs_topological(W.sub(0), facetdim, bndry_facets1) bc0 = dirichletbc(bc_value, bdofsW0_P2_0, W.sub(0)) bc1 = dirichletbc(bc_value, bdofsW0_P2_1, W.sub(0)) A = assemble_matrix(a, bcs=[bc0, bc1]) A.assemble() P = assemble_matrix(p_form, bcs=[bc0, bc1]) P.assemble() b = assemble_vector(L) apply_lifting(b, [a], bcs=[[bc0, bc1]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc0, bc1]) ksp = PETSc.KSP() ksp.create(mesh.comm) ksp.setOperators(A, P) ksp.setType("minres") pc = ksp.getPC() pc.setType('lu') def monitor(ksp, its, rnorm): # print("Num it, rnorm:", its, rnorm) pass ksp.setTolerances(rtol=1.0e-8, max_it=50) ksp.setMonitor(monitor) ksp.setFromOptions() x = A.createVecRight() ksp.solve(b, x) assert ksp.getConvergedReason() > 0 return b.norm(), x.norm(), A.norm(), P.norm()
def plot_scalar(): # We start by creating a unit square mesh and interpolating a function # into a first order Lagrange space msh = create_unit_square(MPI.COMM_WORLD, 12, 12, cell_type=CellType.quadrilateral) V = FunctionSpace(msh, ("Lagrange", 1)) u = Function(V, dtype=np.float64) u.interpolate(lambda x: np.sin(np.pi * x[0]) * np.sin(2 * x[1] * np.pi)) # As we want to visualize the function u, we have to create a grid to # attached the dof values to We do this by creating a topology and # geometry based on the function space V cells, types, x = plot.create_vtk_mesh(V) grid = pyvista.UnstructuredGrid(cells, types, x) grid.point_data["u"] = u.x.array # We set the function "u" as the active scalar for the mesh, and warp # the mesh in z-direction by its values grid.set_active_scalars("u") warped = grid.warp_by_scalar() # We create a plotting window consisting of to plots, one of the scalar # values, and one where the mesh is warped by these values subplotter = pyvista.Plotter(shape=(1, 2)) subplotter.subplot(0, 0) subplotter.add_text("Scalar countour field", font_size=14, color="black", position="upper_edge") subplotter.add_mesh(grid, show_edges=True, show_scalar_bar=True) subplotter.view_xy() subplotter.subplot(0, 1) subplotter.add_text("Warped function", position="upper_edge", font_size=14, color="black") sargs = dict(height=0.8, width=0.1, vertical=True, position_x=0.05, position_y=0.05, fmt="%1.2e", title_font_size=40, color="black", label_font_size=25) subplotter.set_position([-3, 2.6, 0.3]) subplotter.set_focus([3, -1, -0.15]) subplotter.set_viewup([0, 0, 1]) subplotter.add_mesh(warped, show_edges=True, scalar_bar_args=sargs) if pyvista.OFF_SCREEN: subplotter.screenshot("2D_function_warp.png", transparent_background=transparent, window_size=[figsize, figsize]) else: subplotter.show()
def run_scalar_test(mesh, V, degree): """ Manufactured Poisson problem, solving u = x[1]**p, where p is the degree of the Lagrange function space. """ u, v = TrialFunction(V), TestFunction(V) a = inner(grad(u), grad(v)) * dx # Get quadrature degree for bilinear form integrand (ignores effect of non-affine map) a = inner(grad(u), grad(v)) * dx(metadata={"quadrature_degree": -1}) a.integrals()[0].metadata( )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(a) a = form(a) # Source term x = SpatialCoordinate(mesh) u_exact = x[1]**degree f = -div(grad(u_exact)) # Set quadrature degree for linear form integrand (ignores effect of non-affine map) L = inner(f, v) * dx(metadata={"quadrature_degree": -1}) L.integrals()[0].metadata( )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(L) L = form(L) u_bc = Function(V) u_bc.interpolate(lambda x: x[1]**degree) # Create Dirichlet boundary condition facetdim = mesh.topology.dim - 1 mesh.topology.create_connectivity(facetdim, mesh.topology.dim) bndry_facets = np.where( np.array(compute_boundary_facets(mesh.topology)) == 1)[0] bdofs = locate_dofs_topological(V, facetdim, bndry_facets) bc = dirichletbc(u_bc, bdofs) b = assemble_vector(L) apply_lifting(b, [a], bcs=[[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) a = form(a) A = assemble_matrix(a, bcs=[bc]) A.assemble() # Create LU linear solver solver = PETSc.KSP().create(MPI.COMM_WORLD) solver.setType(PETSc.KSP.Type.PREONLY) solver.getPC().setType(PETSc.PC.Type.LU) solver.setOperators(A) uh = Function(V) solver.solve(b, uh.vector) uh.x.scatter_forward() M = (u_exact - uh)**2 * dx M = form(M) error = mesh.comm.allreduce(assemble_scalar(M), op=MPI.SUM) assert np.absolute(error) < 1.0e-14
def test_mixed_interpolation(): """Test that mixed interpolation raised an exception.""" mesh = one_cell_mesh(CellType.triangle) A = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1) B = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 1) v = Function(FunctionSpace(mesh, ufl.MixedElement([A, B]))) with pytest.raises(RuntimeError): v.interpolate(lambda x: (x[1], 2 * x[0], 3 * x[1]))
def test_mixed_fides_functions(tempdir, dim, simplex): """Test saving P2 and P1 functions with Fides""" mesh = generate_mesh(dim, simplex) v = Function(VectorFunctionSpace(mesh, ("Lagrange", 2))) q = Function(FunctionSpace(mesh, ("Lagrange", 1))) filename = os.path.join(tempdir, "v.bp") with pytest.raises(RuntimeError): FidesWriter(mesh.comm, filename, [v, q])
def test_vtx_functions_fail(tempdir, dim, simplex): "Test for error when elements differ" mesh = generate_mesh(dim, simplex) v = Function(VectorFunctionSpace(mesh, ("Lagrange", 2))) w = Function(FunctionSpace(mesh, ("Lagrange", 1))) filename = os.path.join(tempdir, "v.bp") with pytest.raises(RuntimeError): VTXWriter(mesh.comm, filename, [v, w])
def test_interpolation_function(mesh): V = FunctionSpace(mesh, ("Lagrange", 1)) u = Function(V) u.x.array[:] = 1 Vh = FunctionSpace(mesh, ("Lagrange", 1)) uh = Function(Vh) uh.interpolate(u) assert np.allclose(uh.x.array, 1)
def test_vtx_different_meshes_function(tempdir, simplex): "Test for error when functions do not share a mesh" mesh = generate_mesh(2, simplex) v = Function(FunctionSpace(mesh, ("Lagrange", 1))) mesh2 = generate_mesh(2, simplex) w = Function(FunctionSpace(mesh2, ("Lagrange", 1))) filename = os.path.join(tempdir, "v.bp") with pytest.raises(RuntimeError): VTXWriter(mesh.comm, filename, [v, w])
def test_vtx_functions_fail(tempdir, dim, simplex): "Test saving high order Lagrange functions" from dolfinx.cpp.io import VTXWriter mesh = generate_mesh(dim, simplex) v = Function(VectorFunctionSpace(mesh, ("Lagrange", 2))) w = Function(FunctionSpace(mesh, ("Lagrange", 1))) filename = os.path.join(tempdir, "v.bp") with pytest.raises(RuntimeError): VTXWriter(mesh.comm, filename, [v._cpp_object, w._cpp_object])
def test_assembly_dx_domains(mode, meshtags_factory): mesh = create_unit_square(MPI.COMM_WORLD, 10, 10, ghost_mode=mode) V = FunctionSpace(mesh, ("Lagrange", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) # Prepare a marking structures # indices cover all cells # values are [1, 2, 3, 3, ...] cell_map = mesh.topology.index_map(mesh.topology.dim) num_cells = cell_map.size_local + cell_map.num_ghosts indices = np.arange(0, num_cells) values = np.full(indices.shape, 3, dtype=np.intc) values[0] = 1 values[1] = 2 marker = meshtags_factory(mesh, mesh.topology.dim, indices, values) dx = ufl.Measure('dx', subdomain_data=marker, domain=mesh) w = Function(V) w.x.array[:] = 0.5 # Assemble matrix a = form(w * ufl.inner(u, v) * (dx(1) + dx(2) + dx(3))) A = assemble_matrix(a) A.assemble() a2 = form(w * ufl.inner(u, v) * dx) A2 = assemble_matrix(a2) A2.assemble() assert (A - A2).norm() < 1.0e-12 bc = dirichletbc(Function(V), range(30)) # Assemble vector L = form(ufl.inner(w, v) * (dx(1) + dx(2) + dx(3))) b = assemble_vector(L) apply_lifting(b, [a], [[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) L2 = form(ufl.inner(w, v) * dx) b2 = assemble_vector(L2) apply_lifting(b2, [a], [[bc]]) b2.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) set_bc(b2, [bc]) assert (b - b2).norm() < 1.0e-12 # Assemble scalar L = form(w * (dx(1) + dx(2) + dx(3))) s = assemble_scalar(L) s = mesh.comm.allreduce(s, op=MPI.SUM) assert s == pytest.approx(0.5, 1.0e-12) L2 = form(w * dx) s2 = assemble_scalar(L2) s2 = mesh.comm.allreduce(s2, op=MPI.SUM) assert s == pytest.approx(s2, 1.0e-12)
def test_functions_from_different_meshes_fides(tempdir): """Check that the underlying ADIOS2Writer catches sending in functions on different meshes""" filename = os.path.join(tempdir, "mesh_fides.bp") mesh0 = create_unit_square(MPI.COMM_WORLD, 5, 5) mesh1 = create_unit_square(MPI.COMM_WORLD, 10, 2) u0 = Function(FunctionSpace(mesh0, ("Lagrange", 1))) u1 = Function(FunctionSpace(mesh1, ("Lagrange", 1))) with pytest.raises(RuntimeError): FidesWriter(mesh0.comm, filename, [u0, u1])
def test_dof_coords_3d(degree): mesh = create_unit_cube(MPI.COMM_WORLD, 10, 10, 10) V = FunctionSpace(mesh, ("Lagrange", degree)) u = Function(V) u.interpolate(lambda x: x[0]) u.x.scatter_forward() x = V.tabulate_dof_coordinates() val = u.vector.array for i in range(len(val)): assert np.isclose(x[i, 0], val[i], rtol=1e-3)
def test_assemble_empty_rank_mesh(): """Assembly on mesh where some ranks are empty""" comm = MPI.COMM_WORLD cell_type = CellType.triangle domain = ufl.Mesh( ufl.VectorElement("Lagrange", ufl.Cell(cell_type.name), 1)) def partitioner(comm, nparts, local_graph, num_ghost_nodes, ghosting): """Leave cells on the curent rank""" dest = np.full(len(cells), comm.rank, dtype=np.int32) return graph.create_adjacencylist(dest) if comm.rank == 0: # Put cells on rank 0 cells = np.array([[0, 1, 2], [0, 2, 3]], dtype=np.int64) cells = graph.create_adjacencylist(cells) x = np.array([[0., 0.], [1., 0.], [1., 1.], [0., 1.]]) else: # No cells onm other ranks cells = graph.create_adjacencylist(np.empty((0, 3), dtype=np.int64)) x = np.empty((0, 2), dtype=np.float64) mesh = create_mesh(comm, cells, x, domain, GhostMode.none, partitioner) V = FunctionSpace(mesh, ("Lagrange", 2)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) f, k, zero = Function(V), Function(V), Function(V) f.x.array[:] = 10.0 k.x.array[:] = 1.0 zero.x.array[:] = 0.0 a = form(inner(k * u, v) * dx + inner(zero * u, v) * ds) L = form(inner(f, v) * dx + inner(zero, v) * ds) M = form(2 * k * dx + k * ds) sum = comm.allreduce(assemble_scalar(M), op=MPI.SUM) assert sum == pytest.approx(6.0) # Assemble A = assemble_matrix(a) A.assemble() b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) # Solve ksp = PETSc.KSP() ksp.create(mesh.comm) ksp.setOperators(A) ksp.setTolerances(rtol=1.0e-9, max_it=50) ksp.setFromOptions() x = b.copy() ksp.solve(b, x) assert np.allclose(x.array, 10.0)
def test_collapse(W, V): Vs = W.sub(2) with pytest.raises(RuntimeError): Function(Vs) assert Vs.dofmap.cell_dofs(0)[0] != V.dofmap.cell_dofs(0)[0] # Collapse the space it should now be the same as V Vc = Vs.collapse()[0] assert Vc.dofmap.cell_dofs(0)[0] == V.dofmap.cell_dofs(0)[0] f0 = Function(V) f1 = Function(Vc) assert f0.vector.getSize() == f1.vector.getSize()
def test_rank1_hdiv(): """Test rank-1 Expression, i.e. Expression containing Argument (TrialFunction) Test compiles linear interpolation operator RT_2 -> vector DG_2 and assembles it into global matrix A. Input space RT_2 is chosen because it requires dof permutations. """ mesh = create_unit_square(MPI.COMM_WORLD, 10, 10) vdP1 = VectorFunctionSpace(mesh, ("DG", 2)) RT1 = FunctionSpace(mesh, ("RT", 2)) f = ufl.TrialFunction(RT1) points = vdP1.element.interpolation_points compiled_expr = Expression(f, points) num_cells = mesh.topology.index_map(2).size_local array_evaluated = compiled_expr.eval(np.arange(num_cells, dtype=np.int32)) @numba.njit def scatter(A, array_evaluated, dofmap0, dofmap1): for i in range(num_cells): rows = dofmap0[i, :] cols = dofmap1[i, :] A_local = array_evaluated[i, :] MatSetValues(A, 12, rows.ctypes, 8, cols.ctypes, A_local.ctypes, 1) a = form(ufl.inner(f, ufl.TestFunction(vdP1)) * ufl.dx) sparsity_pattern = create_sparsity_pattern(a) sparsity_pattern.assemble() A = create_matrix(MPI.COMM_WORLD, sparsity_pattern) dofmap_col = RT1.dofmap.list.array.reshape(-1, 8).astype( np.dtype(PETSc.IntType)) dofmap_row = vdP1.dofmap.list.array dofmap_row_unrolled = (2 * np.repeat(dofmap_row, 2).reshape(-1, 2) + np.arange(2)).flatten() dofmap_row = dofmap_row_unrolled.reshape(-1, 12).astype( np.dtype(PETSc.IntType)) scatter(A.handle, array_evaluated, dofmap_row, dofmap_col) A.assemble() g = Function(RT1, name="g") def expr1(x): return np.row_stack((np.sin(x[0]), np.cos(x[1]))) # Interpolate a numpy expression into RT1 g.interpolate(expr1) # Interpolate RT1 into vdP1 (non-compiled interpolation) h = Function(vdP1) h.interpolate(g) # Interpolate RT1 into vdP1 (compiled, mat-vec interpolation) h2 = Function(vdP1) h2.vector.axpy(1.0, A * g.vector) assert np.isclose((h2.vector - h.vector).norm(), 0.0)
def test_eval_manifold(): # Simple two-triangle surface in 3d vertices = [(0.0, 0.0, 1.0), (1.0, 1.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0)] cells = [(0, 1, 2), (0, 1, 3)] cell = ufl.Cell("triangle", geometric_dimension=3) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 1)) mesh = create_mesh(MPI.COMM_WORLD, cells, vertices, domain) Q = FunctionSpace(mesh, ("Lagrange", 1)) u = Function(Q) u.interpolate(lambda x: x[0] + x[1]) assert np.isclose(u.eval([0.75, 0.25, 0.5], 0)[0], 1.0)
def test_interpolation_n2curl_to_bdm(tdim, order): if tdim == 2: mesh = create_unit_square(MPI.COMM_WORLD, 5, 5) else: mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2) V = FunctionSpace(mesh, ("N2curl", order)) V1 = FunctionSpace(mesh, ("BDM", order)) u, v = Function(V), Function(V1) u.interpolate(lambda x: x[:tdim]**order) v.interpolate(u) s = assemble_scalar(form(ufl.inner(u - v, u - v) * ufl.dx)) assert np.isclose(s, 0)