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 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_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 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_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_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_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_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_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_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 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_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_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_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 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_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_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)
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_plus_minus_vector(cell_type, pm1, pm2): """Test that ('+') and ('-') match up with the correct DOFs for DG functions""" results = [] orders = [] spaces = [] for count in range(3): for agree in [True, False]: # Two cell mesh with randomly numbered points mesh, order = two_unit_cells(cell_type, agree, return_order=True) if cell_type in [ CellType.interval, CellType.triangle, CellType.tetrahedron ]: V = FunctionSpace(mesh, ("DG", 1)) else: V = FunctionSpace(mesh, ("DQ", 1)) # Assemble vectors with combinations of + and - for a few # different numberings f = Function(V) f.interpolate(lambda x: x[0] - 2 * x[1]) v = ufl.TestFunction(V) a = form(ufl.inner(f(pm1), v(pm2)) * ufl.dS) result = assemble_vector(a) result.assemble() spaces.append(V) results.append(result) orders.append(order) # Check that the above vectors all have the same values as the first # one, but permuted due to differently ordered dofs dofmap0 = spaces[0].mesh.geometry.dofmap for result, space in zip(results[1:], spaces[1:]): # Get the data relating to two results dofmap1 = space.mesh.geometry.dofmap # For each cell for cell in range(2): # For each point in cell 0 in the first mesh for dof0, point0 in zip(spaces[0].dofmap.cell_dofs(cell), dofmap0.links(cell)): # Find the point in the cell 0 in the second mesh for dof1, point1 in zip(space.dofmap.cell_dofs(cell), dofmap1.links(cell)): if np.allclose(spaces[0].mesh.geometry.x[point0], space.mesh.geometry.x[point1]): break else: # If no matching point found, fail assert False assert np.isclose(results[0][dof0], result[dof1])
def monolithic_solve(): """Monolithic version""" E = P * P W = FunctionSpace(mesh, E) U = Function(W) dU = ufl.TrialFunction(W) u0, u1 = ufl.split(U) v0, v1 = ufl.TestFunctions(W) F = inner((u0**2 + 1) * ufl.grad(u0), ufl.grad(v0)) * dx \ + inner((u1**2 + 1) * ufl.grad(u1), ufl.grad(v1)) * dx \ - inner(f, v0) * ufl.dx - inner(g, v1) * dx J = derivative(F, U, dU) F, J = form(F), form(J) u0_bc = Function(V0) u0_bc.interpolate(bc_val_0) u1_bc = Function(V1) u1_bc.interpolate(bc_val_1) bdofsW0_V0 = locate_dofs_topological((W.sub(0), V0), facetdim, bndry_facets) bdofsW1_V1 = locate_dofs_topological((W.sub(1), V1), facetdim, bndry_facets) bcs = [ dirichletbc(u0_bc, bdofsW0_V0, W.sub(0)), dirichletbc(u1_bc, bdofsW1_V1, W.sub(1)) ] Jmat = create_matrix(J) Fvec = create_vector(F) snes = PETSc.SNES().create(MPI.COMM_WORLD) snes.setTolerances(rtol=1.0e-15, max_it=10) snes.getKSP().setType("preonly") snes.getKSP().getPC().setType("lu") problem = NonlinearPDE_SNESProblem(F, J, U, bcs) snes.setFunction(problem.F_mono, Fvec) snes.setJacobian(problem.J_mono, J=Jmat, P=None) U.sub(0).interpolate(initial_guess_u) U.sub(1).interpolate(initial_guess_p) x = create_vector(F) x.array = U.vector.array_r snes.solve(None, x) assert snes.getKSP().getConvergedReason() > 0 assert snes.getConvergedReason() > 0 return x.norm()
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_viz(): Lx = 1.0 Ly = 0.1 _nel = 30 gmsh_model, tdim = mesh_bar_gmshapi("bar", Lx, Ly, 1/_nel, 2) mesh, mts = gmsh_model_to_mesh( gmsh_model, cell_data=False, facet_data=True, gdim=2) element_u = ufl.VectorElement("Lagrange", mesh.ufl_cell(), degree=1, dim=2) V_u = dolfinx.fem.FunctionSpace(mesh, element_u) element_alpha = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), degree=1) V_alpha = dolfinx.fem.FunctionSpace(mesh, element_alpha) def scal_2D(x): return np.sin(np.pi * x[0] * 3.0) def vect_2D(x): vals = np.zeros((2, x.shape[1])) vals[0] = np.sin(x[1]) vals[1] = 0.1 * x[0] return vals # Define the state u = Function(V_u, name="Displacement") u.interpolate(vect_2D) alpha = Function(V_alpha, name="Damage") alpha.interpolate(scal_2D) xvfb.start_xvfb(wait=0.05) pyvista.OFF_SCREEN = True plotter = pyvista.Plotter( title="Test Viz", window_size=[1600, 600], shape=(1, 2), ) _plt = plot_scalar(alpha, plotter, subplot=(0, 0)) logging.critical('plotted scalar') _plt = plot_vector(u, plotter, subplot=(0, 1)) logging.critical('plotted vector') _plt.screenshot(f"./output/test_viz/test_viz_MPI{comm.size}-.png") if not pyvista.OFF_SCREEN: plotter.show()
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_1d_vector(tempdir): mesh = create_unit_interval(MPI.COMM_WORLD, 32) def f(x): vals = np.zeros((2, x.shape[1])) vals[0] = x[0] vals[1] = 2 * x[0] * x[0] return vals element = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2, dim=2) u = Function(FunctionSpace(mesh, element)) u.interpolate(f) filename = os.path.join(tempdir, "u.pvd") with VTKFile(MPI.COMM_WORLD, filename, "w") as vtk: vtk.write_function(u, 0.)
def test_save_vtkx_cell_point(tempdir): """Test writing point-wise data""" mesh = create_unit_square(MPI.COMM_WORLD, 8, 5) P = ufl.FiniteElement("Discontinuous Lagrange", mesh.ufl_cell(), 0) V = FunctionSpace(mesh, P) u = Function(V) u.interpolate(lambda x: 0.5 * x[0]) u.name = "A" filename = os.path.join(tempdir, "v.bp") with pytest.raises(RuntimeError): f = VTXWriter(mesh.comm, filename, [u]) f.write(0) f.close()
def test_plus_minus(cell_type, space_type): """Test that ('+') and ('-') give the same value for continuous functions""" results = [] for count in range(3): for agree in [True, False]: mesh = two_unit_cells(cell_type, agree) V = FunctionSpace(mesh, (space_type, 1)) v = Function(V) v.interpolate(lambda x: x[0] - 2 * x[1]) # Check that these two integrals are equal for pm1, pm2 in product(["+", "-"], repeat=2): a = form(v(pm1) * v(pm2) * ufl.dS) results.append(assemble_scalar(a)) for i, j in combinations(results, 2): assert np.isclose(i, j)
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_interpolation_rank1(W): def f(x): values = np.empty((3, x.shape[1])) values[0] = 1.0 values[1] = 1.0 values[2] = 1.0 return values w = Function(W) w.interpolate(f) x = w.vector assert x.max()[1] == 1.0 assert x.min()[1] == 1.0 num_vertices = W.mesh.topology.index_map(0).size_global assert round(w.vector.norm(PETSc.NormType.N1) - 3 * num_vertices, 7) == 0