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_plus_minus_matrix(cell_type, pm1, pm2): """Test that ('+') and ('-') match up with the correct DOFs for DG functions""" results = [] spaces = [] orders = [] 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) V = FunctionSpace(mesh, ("DG", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) # Assemble matrices with combinations of + and - for a few # different numberings a = form(ufl.inner(u(pm1), v(pm2)) * ufl.dS) result = assemble_matrix(a, []) result.assemble() spaces.append(V) results.append(result) orders.append(order) # Check that the above matrices all have the same values, 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 dof_order = [] # 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 dof_order.append((dof0, dof1)) # For all dof pairs, check that entries in the matrix agree for a, b in dof_order: for c, d in dof_order: assert np.isclose(results[0][a, c], result[b, d])
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_refine_create_form(): """Check that forms can be assembled on refined mesh""" mesh = create_unit_cube(MPI.COMM_WORLD, 3, 3, 3) mesh.topology.create_entities(1) mesh = refine(mesh, redistribute=True) V = FunctionSpace(mesh, ("Lagrange", 1)) # Define variational problem u = ufl.TrialFunction(V) v = ufl.TestFunction(V) a = form(ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx) assemble_matrix(a)
def test_coefficents_non_constant(): "Test packing coefficients with non-constant values" mesh = create_unit_square(MPI.COMM_WORLD, 3, 5) V = FunctionSpace(mesh, ("Lagrange", 3)) # degree 3 so that interpolation is exact u = Function(V) u.interpolate(lambda x: x[0] * x[1]**2) x = SpatialCoordinate(mesh) v = ufl.TestFunction(V) # -- Volume integral vector F = form((ufl.inner(u, v) - ufl.inner(x[0] * x[1]**2, v)) * dx) b0 = assemble_vector(F) b0.assemble() assert np.linalg.norm(b0.array) == pytest.approx(0.0) # -- Exterior facet integral vector F = form((ufl.inner(u, v) - ufl.inner(x[0] * x[1]**2, v)) * ds) b0 = assemble_vector(F) b0.assemble() assert np.linalg.norm(b0.array) == pytest.approx(0.0) # -- Interior facet integral vector V = FunctionSpace(mesh, ("DG", 3)) # degree 3 so that interpolation is exact u0 = Function(V) u0.interpolate(lambda x: x[1]**2) u1 = Function(V) u1.interpolate(lambda x: x[0]) x = SpatialCoordinate(mesh) v = ufl.TestFunction(V) F = (ufl.inner(u1('+') * u0('-'), ufl.avg(v)) - ufl.inner(x[0] * x[1]**2, ufl.avg(v))) * ufl.dS F = form(F) b0 = assemble_vector(F) b0.assemble() assert np.linalg.norm(b0.array) == pytest.approx(0.0)
def test_vtx_single_function(tempdir, dim, simplex): "Test saving a single first order Lagrange functions" mesh = generate_mesh(dim, simplex) v = Function(FunctionSpace(mesh, ("Lagrange", 1))) filename = os.path.join(tempdir, "v.bp") writer = VTXWriter(mesh.comm, filename, v) writer.write(0) writer.close() filename = os.path.join(tempdir, "v2.bp") writer = VTXWriter(mesh.comm, filename, v._cpp_object) writer.write(0) writer.close()
def run_symmetry_test(cell_type, element, form_f): 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) space = FunctionSpace(mesh, element) u = ufl.TrialFunction(space) v = ufl.TestFunction(space) f = form(form_f(u, v)) A = dolfinx.fem.assemble_matrix(f) A.assemble() check_symmetry(A)
def test_complex_assembly(): """Test assembly of complex matrices and vectors""" mesh = create_unit_square(MPI.COMM_WORLD, 10, 10) P2 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 2) V = FunctionSpace(mesh, P2) u = ufl.TrialFunction(V) v = ufl.TestFunction(V) g = -2 + 3.0j j = 1.0j a_real = form(inner(u, v) * dx) L1 = form(inner(g, v) * dx) b = assemble_vector(L1) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) bnorm = b.norm(PETSc.NormType.N1) b_norm_ref = abs(-2 + 3.0j) assert bnorm == pytest.approx(b_norm_ref) A = assemble_matrix(a_real) A.assemble() A0_norm = A.norm(PETSc.NormType.FROBENIUS) x = ufl.SpatialCoordinate(mesh) a_imag = form(j * inner(u, v) * dx) f = 1j * ufl.sin(2 * np.pi * x[0]) L0 = form(inner(f, v) * dx) A = assemble_matrix(a_imag) A.assemble() A1_norm = A.norm(PETSc.NormType.FROBENIUS) assert A0_norm == pytest.approx(A1_norm) b = assemble_vector(L0) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) b1_norm = b.norm(PETSc.NormType.N2) a_complex = form((1 + j) * inner(u, v) * dx) f = ufl.sin(2 * np.pi * x[0]) L2 = form(inner(f, v) * dx) A = assemble_matrix(a_complex) A.assemble() A2_norm = A.norm(PETSc.NormType.FROBENIUS) assert A1_norm == pytest.approx(A2_norm / np.sqrt(2)) b = assemble_vector(L2) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) b2_norm = b.norm(PETSc.NormType.N2) assert b2_norm == pytest.approx(b1_norm)
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_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_extract_forms(): """Test extraction on unique function spaces for rows and columns of a block system""" mesh = create_unit_square(MPI.COMM_WORLD, 32, 31) V0 = FunctionSpace(mesh, ("Lagrange", 1)) V1 = FunctionSpace(mesh, ("Lagrange", 2)) V2 = V0.clone() V3 = V1.clone() v0, u0 = TestFunction(V0), TrialFunction(V0) v1, u1 = TestFunction(V1), TrialFunction(V1) v2, u2 = TestFunction(V2), TrialFunction(V2) v3, u3 = TestFunction(V3), TrialFunction(V3) a = form([[inner(u0, v0) * dx, inner(u1, v1) * dx], [inner(u2, v2) * dx, inner(u3, v3) * dx]]) with pytest.raises(AssertionError): extract_function_spaces(a, 0) with pytest.raises(AssertionError): extract_function_spaces(a, 1) a = form([[inner(u0, v0) * dx, inner(u2, v1) * dx], [inner(u0, v2) * dx, inner(u2, v2) * dx]]) with pytest.raises(AssertionError): extract_function_spaces(a, 0) Vc = extract_function_spaces(a, 1) assert Vc[0] is V0._cpp_object assert Vc[1] is V2._cpp_object a = form([[inner(u0, v0) * dx, inner(u1, v0) * dx], [inner(u2, v1) * dx, inner(u3, v1) * dx]]) Vr = extract_function_spaces(a, 0) assert Vr[0] is V0._cpp_object assert Vr[1] is V1._cpp_object with pytest.raises(AssertionError): extract_function_spaces(a, 1)
def perform_test(points, cells): domain = ufl.Mesh(ufl.VectorElement("Lagrange", "tetrahedron", 1)) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) V = FunctionSpace(mesh, (space_type, order)) f = Function(V) output = [] for dof in range(len(f.vector[:])): f.vector[:] = np.zeros(len(f.vector[:])) f.vector[dof] = 1 points = np.array([[1 / 3, 1 / 3, 1 / 3], [1 / 3, 1 / 3, 1 / 3]]) cells = np.array([0, 1]) result = f.eval(points, cells) normal = np.array([1., 1., 1.]) output.append(result.dot(normal)) return output
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_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_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_complex_assembly_solve(): """Solve a positive definite helmholtz problem and verify solution with the method of manufactured solutions""" degree = 3 mesh = create_unit_square(MPI.COMM_WORLD, 20, 20) P = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), degree) V = FunctionSpace(mesh, P) x = ufl.SpatialCoordinate(mesh) # Define source term A = 1.0 + 2.0 * (2.0 * np.pi)**2 f = (1. + 1j) * A * ufl.cos(2 * np.pi * x[0]) * ufl.cos(2 * np.pi * x[1]) # Variational problem u, v = ufl.TrialFunction(V), ufl.TestFunction(V) C = 1.0 + 1.0j a = form(C * inner(grad(u), grad(v)) * dx + C * inner(u, v) * dx) L = form(inner(f, v) * dx) # Assemble A = assemble_matrix(a) A.assemble() b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) # Create solver solver = PETSc.KSP().create(mesh.comm) solver.setOptionsPrefix("test_lu_") opts = PETSc.Options("test_lu_") opts["ksp_type"] = "preonly" opts["pc_type"] = "lu" solver.setFromOptions() x = A.createVecRight() solver.setOperators(A) solver.solve(b, x) # Reference Solution def ref_eval(x): return np.cos(2 * np.pi * x[0]) * np.cos(2 * np.pi * x[1]) u_ref = Function(V) u_ref.interpolate(ref_eval) diff = (x - u_ref.vector).norm(PETSc.NormType.N2) assert diff == pytest.approx(0.0, abs=1e-1)
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_basic_interior_facet_assembly(): mesh = create_rectangle(MPI.COMM_WORLD, [np.array([0.0, 0.0]), np.array([1.0, 1.0])], [5, 5], cell_type=CellType.triangle, ghost_mode=GhostMode.shared_facet) V = FunctionSpace(mesh, ("DG", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = ufl.inner(ufl.avg(u), ufl.avg(v)) * ufl.dS a = form(a) A = assemble_matrix(a) A.assemble() assert isinstance(A, PETSc.Mat) L = ufl.conj(ufl.avg(v)) * ufl.dS L = form(L) b = assemble_vector(L) b.assemble() assert isinstance(b, PETSc.Vec)
def test_ghost_mesh_dS_assembly(mode, dS): 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) dS = dS(mesh) a = form(inner(avg(u), avg(v)) * dS) # Initial assembly A = fem.assemble_matrix(a) A.assemble() assert isinstance(A, PETSc.Mat) # Check that the norms are the same for all three modes normA = A.norm() print(normA) assert normA == pytest.approx(2.1834054713561906, rel=1.e-6, abs=1.e-12)
def test_basic_assembly(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) f = Function(V) f.x.array[:] = 10.0 a = inner(f * u, v) * dx + inner(u, v) * ds L = inner(f, v) * dx + inner(2.0, v) * ds a, L = form(a), form(L) # Initial assembly A = assemble_matrix(a) A.assemble() assert isinstance(A, PETSc.Mat) b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) assert isinstance(b, PETSc.Vec) # Second assembly normA = A.norm() A.zeroEntries() A = assemble_matrix(A, a) A.assemble() assert isinstance(A, PETSc.Mat) assert normA == pytest.approx(A.norm()) normb = b.norm() with b.localForm() as b_local: b_local.set(0.0) b = assemble_vector(b, L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) assert isinstance(b, PETSc.Vec) assert normb == pytest.approx(b.norm()) # Vector re-assembly - no zeroing (but need to zero ghost entries) with b.localForm() as b_local: b_local.array[b.local_size:] = 0.0 assemble_vector(b, L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) assert 2.0 * normb == pytest.approx(b.norm()) # Matrix re-assembly (no zeroing) assemble_matrix(A, a) A.assemble() assert 2.0 * normA == pytest.approx(A.norm())
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_overlapping_bcs(): """Test that, when boundaries condition overlap, the last provided boundary condition is applied""" n = 23 mesh = create_unit_square(MPI.COMM_WORLD, n, n) V = FunctionSpace(mesh, ("Lagrange", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = form(inner(u, v) * dx) L = form(inner(1, v) * dx) dofs_left = locate_dofs_geometrical(V, lambda x: x[0] < 1.0 / (2.0 * n)) dofs_top = locate_dofs_geometrical(V, lambda x: x[1] > 1.0 - 1.0 / (2.0 * n)) dof_corner = np.array(list(set(dofs_left).intersection(set(dofs_top))), dtype=np.int64) # Check only one dof pair is found globally assert len(set(np.concatenate(MPI.COMM_WORLD.allgather(dof_corner)))) == 1 bcs = [ dirichletbc(PETSc.ScalarType(0), dofs_left, V), dirichletbc(PETSc.ScalarType(123.456), dofs_top, V) ] A, b = create_matrix(a), create_vector(L) assemble_matrix(A, a, bcs=bcs) A.assemble() # Check the diagonal (only on the rank that owns the row) d = A.getDiagonal() if len(dof_corner) > 0 and dof_corner[0] < V.dofmap.index_map.size_local: assert np.isclose(d.array_r[dof_corner[0]], 1.0) with b.localForm() as b_loc: b_loc.set(0) assemble_vector(b, L) apply_lifting(b, [a], [bcs]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, bcs) b.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) if len(dof_corner) > 0: with b.localForm() as b_loc: assert b_loc[dof_corner[0]] == 123.456
def plot_scalar(): # Plotting a Function using warp by scalar # ======================================== # We start by creating a unit square mesh and interpolating a function # into a first order Lagrange space mesh = create_unit_square(MPI.COMM_WORLD, 12, 12, cell_type=CellType.quadrilateral) V = FunctionSpace(mesh, ("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 test_nonlinear_pde_snes(): """Test Newton solver for a simple nonlinear PDE""" # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 12, 15) V = FunctionSpace(mesh, ("Lagrange", 1)) u = Function(V) v = TestFunction(V) F = inner(5.0, v) * dx - ufl.sqrt(u * u) * inner( grad(u), grad(v)) * dx - inner(u, v) * dx u_bc = Function(V) u_bc.x.array[:] = 1.0 bc = dirichletbc( u_bc, locate_dofs_geometrical( V, lambda x: np.logical_or(np.isclose(x[0], 0.0), np.isclose(x[0], 1.0)))) # Create nonlinear problem problem = NonlinearPDE_SNESProblem(F, u, bc) u.x.array[:] = 0.9 b = la.create_petsc_vector(V.dofmap.index_map, V.dofmap.index_map_bs) J = create_matrix(problem.a) # Create Newton solver and solve snes = PETSc.SNES().create() snes.setFunction(problem.F, b) snes.setJacobian(problem.J, J) snes.setTolerances(rtol=1.0e-9, max_it=10) snes.getKSP().setType("preonly") snes.getKSP().setTolerances(rtol=1.0e-9) snes.getKSP().getPC().setType("lu") snes.solve(None, u.vector) assert snes.getConvergedReason() > 0 assert snes.getIterationNumber() < 6 # Modify boundary condition and solve again u_bc.x.array[:] = 0.6 snes.solve(None, u.vector) assert snes.getConvergedReason() > 0 assert snes.getIterationNumber() < 6
def test_custom_mesh_loop_ctypes_rank2(): """Test numba assembler for bilinear form""" # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 64, 64) V = FunctionSpace(mesh, ("Lagrange", 1)) # Extract mesh and dofmap data num_owned_cells = mesh.topology.index_map(mesh.topology.dim).size_local num_cells = num_owned_cells + mesh.topology.index_map( mesh.topology.dim).num_ghosts x_dofs = mesh.geometry.dofmap.array.reshape(num_cells, 3) x = mesh.geometry.x dofmap = V.dofmap.list.array.reshape(num_cells, 3).astype(np.dtype(PETSc.IntType)) # Generated case with general assembler u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = form(inner(u, v) * dx) A0 = assemble_matrix(a) A0.assemble() A0.zeroEntries() start = time.time() dolfinx.fem.assemble_matrix(A0, a) end = time.time() print("Time (C++, pass 2):", end - start) A0.assemble() # Custom case A1 = A0.copy() for i in range(2): A1.zeroEntries() mat = A1.handle start = time.time() assemble_matrix_ctypes(mat, (x_dofs, x), dofmap, num_owned_cells, MatSetValues_ctypes, PETSc.InsertMode.ADD_VALUES) end = time.time() print("Time (numba, pass {}): {}".format(i, end - start)) A1.assemble() assert (A0 - A1).norm() == pytest.approx(0.0, abs=1.0e-9)
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_evaluation(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) V = FunctionSpace(mesh, (space_type, space_order)) dofs = [i for i in V.dofmap.cell_dofs(0) if i in V.dofmap.cell_dofs(1)] N = 5 if cell_type == "tetrahedron": eval_points = np.array([[0., i / N, j / N] for i in range(N + 1) for j in range(N + 1 - i)]) elif cell_type == "hexahedron": eval_points = np.array([[0., i / N, j / N] for i in range(N + 1) for j in range(N + 1)]) else: eval_points = np.array([[0., i / N, 0.] for i in range(N + 1)]) for d in dofs: v = Function(V) v.vector[:] = [ 1 if i == d else 0 for i in range(v.vector.local_size) ] values0 = v.eval(eval_points, [0 for i in eval_points]) values1 = v.eval(eval_points, [1 for i in eval_points]) if len(eval_points) == 1: values0 = [values0] values1 = [values1] if space_type in ["RT", "BDM", "RTCF", "NCF", "BDMCF", "AAF"]: # Hdiv for i, j in zip(values0, values1): assert np.isclose(i[0], j[0]) elif space_type in [ "N1curl", "N2curl", "RTCE", "NCE", "BDMCE", "AAE" ]: # Hcurl for i, j in zip(values0, values1): assert np.allclose(i[1:], j[1:]) else: assert np.allclose(values0, values1)
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_higher_order_tetra_coordinate_map(order): """ Computes physical coordinates of a cell, based on the coordinate map. """ celltype = CellType.tetrahedron points = np.array([[0, 0, 0], [1, 0, 0], [0, 2, 0], [0, 0, 3], [0, 4 / 3, 1], [0, 2 / 3, 2], [2 / 3, 0, 1], [1 / 3, 0, 2], [2 / 3, 2 / 3, 0], [1 / 3, 4 / 3, 0], [0, 0, 1], [0, 0, 2], [0, 2 / 3, 0], [0, 4 / 3, 0], [1 / 3, 0, 0], [2 / 3, 0, 0], [1 / 3, 2 / 3, 1], [0, 2 / 3, 1], [1 / 3, 0, 1], [1 / 3, 2 / 3, 0]]) if order == 1: points = np.array( [points[0, :], points[1, :], points[2, :], points[3, :]]) elif order == 2: points = np.array([ points[0, :], points[1, :], points[2, :], points[3, :], [0, 1, 3 / 2], [1 / 2, 0, 3 / 2], [1 / 2, 1, 0], [0, 0, 3 / 2], [0, 1, 0], [1 / 2, 0, 0] ]) cells = np.array([range(len(points))]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", celltype.name, order)) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) V = FunctionSpace(mesh, ("Lagrange", order)) X = V.element.interpolation_points coord_dofs = mesh.geometry.dofmap x_g = mesh.geometry.x cmap = mesh.geometry.cmap x_coord_new = np.zeros([len(points), mesh.geometry.dim]) i = 0 for node in range(len(points)): x_coord_new[i] = x_g[coord_dofs.links(0)[node], :mesh.geometry.dim] i += 1 x = cmap.push_forward(X, x_coord_new) assert np.allclose(x[:, 0], X[:, 0]) assert np.allclose(x[:, 1], 2 * X[:, 1]) assert np.allclose(x[:, 2], 3 * X[:, 2])