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 amg_solve(N, method): # Elasticity parameters E = 1.0e9 nu = 0.3 mu = E / (2.0 * (1.0 + nu)) lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)) # Stress computation def sigma(v): return 2.0 * mu * sym(grad(v)) + lmbda * tr(sym( grad(v))) * Identity(2) # Define problem mesh = create_unit_square(MPI.COMM_WORLD, N, N) V = VectorFunctionSpace(mesh, 'Lagrange', 1) u = TrialFunction(V) v = TestFunction(V) facetdim = mesh.topology.dim - 1 bndry_facets = locate_entities_boundary( mesh, facetdim, lambda x: np.full(x.shape[1], True)) bdofs = locate_dofs_topological(V.sub(0), V, facetdim, bndry_facets) bc = dirichletbc(PETSc.ScalarType(0), bdofs, V.sub(0)) # Forms a, L = inner(sigma(u), grad(v)) * dx, dot(ufl.as_vector( (1.0, 1.0)), v) * dx # Assemble linear algebra objects A = assemble_matrix(a, [bc]) A.assemble() b = assemble_vector(L) apply_lifting(b, [a], [[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) # Create solution function u = Function(V) # Create near null space basis and orthonormalize null_space = build_nullspace(V, u.vector) # Attached near-null space to matrix A.set_near_nullspace(null_space) # Test that basis is orthonormal assert null_space.is_orthonormal() # Create PETSC smoothed aggregation AMG preconditioner, and # create CG solver solver = PETSc.KSP().create(mesh.comm) solver.setType("cg") # Set matrix operator solver.setOperators(A) # Compute solution and return number of iterations return solver.solve(b, u.vector)
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_nullspace_check(mesh, degree): V = VectorFunctionSpace(mesh, ('Lagrange', degree)) u, v = TrialFunction(V), TestFunction(V) E, nu = 2.0e2, 0.3 mu = E / (2.0 * (1.0 + nu)) lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)) def sigma(w, gdim): return 2.0 * mu * ufl.sym(grad(w)) + lmbda * ufl.tr( grad(w)) * ufl.Identity(gdim) a = form(inner(sigma(u, mesh.geometry.dim), grad(v)) * dx) # Assemble matrix and create compatible vector A = assemble_matrix(a) A.assemble() # Create null space basis and test nullspace = build_elastic_nullspace(V) la.orthonormalize(nullspace) ns = PETSc.NullSpace().create(vectors=nullspace) assert ns.test(A) # Create incorrect null space basis and test nullspace = build_broken_elastic_nullspace(V) la.orthonormalize(nullspace) ns = PETSc.NullSpace().create(vectors=nullspace) assert not ns.test(A)
def test_vector_assemble_matrix_interior(): mesh = create_unit_square(MPI.COMM_WORLD, 3, 3) V = VectorFunctionSpace(mesh, ("Lagrange", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = form(ufl.inner(ufl.jump(u), ufl.jump(v)) * ufl.dS) A = assemble_matrix(a) A.assemble()
def test_nullspace_orthogonal(mesh, degree): """Test that null spaces orthogonalisation""" V = VectorFunctionSpace(mesh, ('Lagrange', degree)) nullspace = build_elastic_nullspace(V) assert not la.is_orthonormal(nullspace) la.orthonormalize(nullspace) assert la.is_orthonormal(nullspace)
def test_interpolation_vector_elements(order1, order2): mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2) V = VectorFunctionSpace(mesh, ("Lagrange", order1)) V1 = VectorFunctionSpace(mesh, ("Lagrange", order2)) u, v = Function(V), Function(V1) u.interpolate(lambda x: x) v.interpolate(u) s = assemble_scalar(form(ufl.inner(u - v, u - v) * ufl.dx)) assert np.isclose(s, 0) DG = VectorFunctionSpace(mesh, ("DG", order2)) w = Function(DG) w.interpolate(u) s = assemble_scalar(form(ufl.inner(u - w, u - w) * ufl.dx)) assert np.isclose(s, 0)
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_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_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 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_save_3d_vector(tempdir, encoding, cell_type): filename = os.path.join(tempdir, "u_3Dv.xdmf") mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2, cell_type) u = Function(VectorFunctionSpace(mesh, ("Lagrange", 1))) 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 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_vector_element(): # VectorFunctionSpace containing a scalar should work mesh = create_unit_square(MPI.COMM_WORLD, 1, 1, CellType.triangle, GhostMode.shared_facet) U = VectorFunctionSpace(mesh, ("P", 2)) u = ufl.TrialFunction(U) v = ufl.TestFunction(U) a = form(ufl.inner(u, v) * ufl.dx) A = dolfinx.fem.petsc.assemble_matrix(a) A.assemble() with pytest.raises(ValueError): # VectorFunctionSpace containing a vector should throw an error rather than segfaulting U = VectorFunctionSpace(mesh, ("RT", 2)) u = ufl.TrialFunction(U) v = ufl.TestFunction(U) a = form(ufl.inner(u, v) * ufl.dx) A = dolfinx.fem.petsc.assemble_matrix(a) A.assemble()
def test_entity_dofs(mesh): """Test that num entity dofs is correctly wrapped to dolfinx::DofMap""" V = FunctionSpace(mesh, ("Lagrange", 1)) assert V.dofmap.dof_layout.num_entity_dofs(0) == 1 assert V.dofmap.dof_layout.num_entity_dofs(1) == 0 assert V.dofmap.dof_layout.num_entity_dofs(2) == 0 V = VectorFunctionSpace(mesh, ("Lagrange", 1)) bs = V.dofmap.dof_layout.block_size assert V.dofmap.dof_layout.num_entity_dofs(0) * bs == 2 assert V.dofmap.dof_layout.num_entity_dofs(1) * bs == 0 assert V.dofmap.dof_layout.num_entity_dofs(2) * bs == 0 V = FunctionSpace(mesh, ("Lagrange", 2)) assert V.dofmap.dof_layout.num_entity_dofs(0) == 1 assert V.dofmap.dof_layout.num_entity_dofs(1) == 1 assert V.dofmap.dof_layout.num_entity_dofs(2) == 0 V = FunctionSpace(mesh, ("Lagrange", 3)) assert V.dofmap.dof_layout.num_entity_dofs(0) == 1 assert V.dofmap.dof_layout.num_entity_dofs(1) == 2 assert V.dofmap.dof_layout.num_entity_dofs(2) == 1 V = FunctionSpace(mesh, ("DG", 0)) assert V.dofmap.dof_layout.num_entity_dofs(0) == 0 assert V.dofmap.dof_layout.num_entity_dofs(1) == 0 assert V.dofmap.dof_layout.num_entity_dofs(2) == 1 V = FunctionSpace(mesh, ("DG", 1)) assert V.dofmap.dof_layout.num_entity_dofs(0) == 0 assert V.dofmap.dof_layout.num_entity_dofs(1) == 0 assert V.dofmap.dof_layout.num_entity_dofs(2) == 3 V = VectorFunctionSpace(mesh, ("Lagrange", 1)) bs = V.dofmap.dof_layout.block_size for i, cdofs in enumerate([[0, 1], [2, 3], [4, 5]]): dofs = [ bs * d + b for d in V.dofmap.dof_layout.entity_dofs(0, i) for b in range(bs) ] assert all(d == cd for d, cd in zip(dofs, cdofs))
def test_integral(cell_type, space_type, space_order): if cell_type == "hexahedron" and space_order >= 3: pytest.skip("Skipping expensive test on hexahedron") random.seed(4) for repeat in range(10): mesh = random_evaluation_mesh(cell_type) tdim = mesh.topology.dim V = FunctionSpace(mesh, (space_type, space_order)) Vvec = VectorFunctionSpace(mesh, ("P", 1)) dofs = [i for i in V.dofmap.cell_dofs(0) if i in V.dofmap.cell_dofs(1)] for d in dofs: v = Function(V) v.vector[:] = [ 1 if i == d else 0 for i, _ in enumerate(v.vector[:]) ] if space_type in ["RT", "BDM", "RTCF", "NCF", "BDMCF", "AAF"]: # Hdiv def normal(x): values = np.zeros((tdim, x.shape[1])) values[0] = [1 for i in values[0]] return values n = Function(Vvec) n.interpolate(normal) _form = ufl.inner(ufl.jump(v), n) * ufl.dS elif space_type in [ "N1curl", "N2curl", "RTCE", "NCE", "BDMCE", "AAE" ]: # Hcurl def tangent(x): values = np.zeros((tdim, x.shape[1])) values[1] = [1 for i in values[1]] return values t = Function(Vvec) t.interpolate(tangent) _form = ufl.inner(ufl.jump(v), t) * ufl.dS if tdim == 3: def tangent2(x): values = np.zeros((3, x.shape[1])) values[2] = [1 for i in values[2]] return values t2 = Function(Vvec) t2.interpolate(tangent2) _form += ufl.inner(ufl.jump(v), t2) * ufl.dS else: _form = ufl.jump(v) * ufl.dS value = assemble_scalar(form(_form)) assert np.isclose(value, 0)
def test_interpolation_n1curl_to_dg(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, ("N1curl", order + 1)) V1 = VectorFunctionSpace(mesh, ("DG", 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)
def test_add_diagonal(): """Test adding entries to diagonal of sparsity pattern""" mesh = create_unit_square(MPI.COMM_WORLD, 10, 10) V = VectorFunctionSpace(mesh, ("Lagrange", 1)) pattern = SparsityPattern(mesh.comm, [V.dofmap.index_map, V.dofmap.index_map], [V.dofmap.index_map_bs, V.dofmap.index_map_bs]) mesh.topology.create_connectivity(mesh.topology.dim - 1, mesh.topology.dim) facets = compute_boundary_facets(mesh.topology) blocks = locate_dofs_topological(V, mesh.topology.dim - 1, facets) pattern.insert_diagonal(blocks) pattern.assemble() assert len(blocks) == pattern.num_nonzeros
def test_mixed_sub_interpolation(): """Test interpolation of sub-functions""" mesh = create_unit_cube(MPI.COMM_WORLD, 3, 3, 3) def f(x): return np.vstack((10 + x[0], -10 - x[1], 25 + x[0])) P2 = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2) P1 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1) for i, P in enumerate((P2 * P1, P1 * P2)): W = FunctionSpace(mesh, P) U = Function(W) U.sub(i).interpolate(f) # Same element V = FunctionSpace(mesh, P2) u, v = Function(V), Function(V) u.interpolate(U.sub(i)) v.interpolate(f) assert np.allclose(u.vector.array, v.vector.array) # Same map, different elements V = VectorFunctionSpace(mesh, ("Lagrange", 1)) u, v = Function(V), Function(V) u.interpolate(U.sub(i)) v.interpolate(f) assert np.allclose(u.vector.array, v.vector.array) # Different maps (0) V = FunctionSpace(mesh, ("N1curl", 1)) u, v = Function(V), Function(V) u.interpolate(U.sub(i)) v.interpolate(f) assert np.allclose(u.vector.array, v.vector.array) # Different maps (1) V = FunctionSpace(mesh, ("RT", 2)) u, v = Function(V), Function(V) u.interpolate(U.sub(i)) v.interpolate(f) assert np.allclose(u.vector.array, v.vector.array) # Test with wrong shape V0 = FunctionSpace(mesh, P.sub_elements()[0]) V1 = FunctionSpace(mesh, P.sub_elements()[1]) v0, v1 = Function(V0), Function(V1) with pytest.raises(RuntimeError): v0.interpolate(U.sub(1)) with pytest.raises(RuntimeError): v1.interpolate(U.sub(0))
def test_save_2d_vector_CG2(tempdir): points = np.array([[0, 0], [1, 0], [1, 2], [0, 2], [1 / 2, 0], [1, 1], [1 / 2, 2], [0, 1], [1 / 2, 1]]) points = np.array([[0, 0], [1, 0], [0, 2], [0.5, 1], [0, 1], [0.5, 0], [1, 2], [0.5, 2], [1, 1]]) cells = np.array([[0, 1, 2, 3, 4, 5], [1, 6, 2, 7, 3, 8]]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", "triangle", 2)) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) u = Function(VectorFunctionSpace(mesh, ("Lagrange", 2))) u.interpolate(lambda x: np.vstack((x[0], x[1]))) filename = os.path.join(tempdir, "u.pvd") with VTKFile(mesh.comm, filename, "w") as vtk: vtk.write_function(u, 0.)
def test_save_2d_vector(tempdir, cell_type): mesh = create_unit_square(MPI.COMM_WORLD, 16, 16, cell_type=cell_type) u = Function(VectorFunctionSpace(mesh, ("Lagrange", 1))) def f(x): vals = np.zeros((2, x.shape[1])) vals[0] = x[0] vals[1] = 2 * x[0] * x[1] return vals u.interpolate(f) 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_argument_equality(mesh, V, V2, W, W2): """Placed this test here because it's mainly about detecting differing function spaces""" mesh2 = create_unit_cube(MPI.COMM_WORLD, 8, 8, 8) V3 = FunctionSpace(mesh2, ("Lagrange", 1)) W3 = VectorFunctionSpace(mesh2, ("Lagrange", 1)) for TF in (TestFunction, TrialFunction): v = TF(V) v2 = TF(V2) v3 = TF(V3) assert v == v2 assert v2 == v assert V != V3 assert V2 != V3 assert not v == v3 assert not v2 == v3 assert v != v3 assert v2 != v3 assert v != v3 assert v2 != v3 w = TF(W) w2 = TF(W2) w3 = TF(W3) assert w == w2 assert w2 == w assert w != w3 assert w2 != w3 assert v != w assert w != v s1 = set((v, w)) s2 = set((v2, w2)) s3 = set((v, v2, w, w2)) assert len(s1) == 2 assert len(s2) == 2 assert len(s3) == 2 assert s1 == s2 assert s1 == s3 assert s2 == s3 # Test that the dolfinx implementation of Argument.__eq__ is # triggered when comparing ufl expressions assert grad(v) == grad(v2) assert grad(v) != grad(v3)
def test_rank0(): """Test evaluation of UFL expression. This test evaluates gradient of P2 function at interpolation points of vector dP1 element. For a donor function f(x, y) = x^2 + 2*y^2 result is compared with the exact gradient grad f(x, y) = [2*x, 4*y]. """ mesh = create_unit_square(MPI.COMM_WORLD, 5, 5) P2 = FunctionSpace(mesh, ("P", 2)) vdP1 = VectorFunctionSpace(mesh, ("DG", 1)) f = Function(P2) def expr1(x): return x[0]**2 + 2.0 * x[1]**2 f.interpolate(expr1) ufl_expr = ufl.grad(f) points = vdP1.element.interpolation_points compiled_expr = Expression(ufl_expr, 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(vec, array_evaluated, dofmap): for i in range(num_cells): for j in range(3): for k in range(2): vec[2 * dofmap[i * 3 + j] + k] = array_evaluated[i, 2 * j + k] # Data structure for the result b = Function(vdP1) dofmap = vdP1.dofmap.list.array scatter(b.x.array, array_evaluated, dofmap) b.x.scatter_forward() def grad_expr1(x): return np.vstack((2.0 * x[0], 4.0 * x[1])) b2 = Function(vdP1) b2.interpolate(grad_expr1) assert np.allclose(b2.x.array, b.x.array)
def test_vector_interpolation_spatial(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 = VectorFunctionSpace(mesh, ("Lagrange", order)) u = Function(V) x = ufl.SpatialCoordinate(mesh) # The expression (x,y,z)^n is contained in space f = ufl.as_vector([x[i]**order for i in range(dim)]) u.interpolate(Expression(f, V.element.interpolation_points)) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(u - f, u - f) * ufl.dx))), 0)
def test_two_fides_functions(tempdir, dim, simplex): """Test saving two functions with Fides""" mesh = generate_mesh(dim, simplex) v = Function(VectorFunctionSpace(mesh, ("Lagrange", 1))) q = Function(FunctionSpace(mesh, ("Lagrange", 1))) filename = os.path.join(tempdir, "v.bp") with FidesWriter(mesh.comm, filename, [v._cpp_object, q]) as f: f.write(0) def vel(x): values = np.zeros((dim, x.shape[1])) values[0] = x[1] values[1] = x[0] return values v.interpolate(vel) q.interpolate(lambda x: x[0]) f.write(1)
def test_fides_function_at_nodes(tempdir, dim, simplex): """Test saving P1 functions with Fides (with changing geometry)""" from dolfinx.cpp.io import FidesWriter mesh = generate_mesh(dim, simplex) v = Function(VectorFunctionSpace(mesh, ("Lagrange", 1))) q = Function(FunctionSpace(mesh, ("Lagrange", 1))) filename = os.path.join(tempdir, "v.bp") with FidesWriter(mesh.comm, filename, [v._cpp_object, q._cpp_object]) as f: for t in [0.1, 0.5, 1]: # Only change one function q.interpolate(lambda x: t * (x[0] - 0.5)**2) f.write(t) mesh.geometry.x[:, :2] += 0.1 if mesh.geometry.dim == 2: v.interpolate(lambda x: (t * x[0], x[1] + x[1] * 1j)) elif mesh.geometry.dim == 3: v.interpolate(lambda x: (t * x[2], x[0] + x[2] * 2j, x[1])) f.write(t)
def test_basic_assembly_petsc_matrixcsr(mode): mesh = create_unit_square(MPI.COMM_WORLD, 12, 12, ghost_mode=mode) V = FunctionSpace(mesh, ("Lagrange", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = inner(u, v) * dx + inner(u, v) * ds a = form(a) A0 = fem.assemble_matrix(a) A0.finalize() assert isinstance(A0, la.MatrixCSRMetaClass) A1 = fem.petsc.assemble_matrix(a) A1.assemble() assert isinstance(A1, PETSc.Mat) assert np.sqrt(A0.norm_squared()) == pytest.approx(A1.norm()) V = VectorFunctionSpace(mesh, ("Lagrange", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = form(inner(u, v) * dx + inner(u, v) * ds) with pytest.raises(RuntimeError): A0 = fem.assemble_matrix(a)
def test_block_size(mesh): meshes = [ create_unit_square(8, 8), create_unit_cube(4, 4, 4), create_unit_square(8, 8, CellType.quadrilateral), create_unit_cube(4, 4, 4, CellType.hexahedron) ] for mesh in meshes: P2 = FiniteElement("Lagrange", mesh.ufl_cell(), 2) V = FunctionSpace(mesh, P2) assert V.dofmap.bs == 1 V = FunctionSpace(mesh, P2 * P2) assert V.dofmap.index_map_bs == 2 for i in range(1, 6): W = FunctionSpace(mesh, MixedElement(i * [P2])) assert W.dofmap.index_map_bs == i V = VectorFunctionSpace(mesh, ("Lagrange", 2)) assert V.dofmap.index_map_bs == mesh.geometry.dim
def test_vtx_functions(tempdir, dim, simplex): "Test saving high order Lagrange functions" from dolfinx.cpp.io import VTXWriter mesh = generate_mesh(dim, simplex) V = VectorFunctionSpace(mesh, ("DG", 2)) v = Function(V) bs = V.dofmap.index_map_bs def vel(x): values = np.zeros((dim, x.shape[1])) values[0] = x[1] values[1] = x[0] return values v.interpolate(vel) W = FunctionSpace(mesh, ("DG", 2)) w = Function(W) w.interpolate(lambda x: x[0] + x[1]) filename = os.path.join(tempdir, "v.bp") f = VTXWriter(mesh.comm, filename, [v._cpp_object, w._cpp_object]) # Set two cells to 0 for c in [0, 1]: dofs = np.asarray([V.dofmap.cell_dofs(c) * bs + b for b in range(bs)], dtype=np.int32) v.x.array[dofs] = 0 w.x.array[W.dofmap.cell_dofs(c)] = 1 v.x.scatter_forward() w.x.scatter_forward() # Save twice and update geometry for t in [0.1, 1]: mesh.geometry.x[:, :2] += 0.1 f.write(t) f.close()