def test_nedelec_spatial(order, dim): if dim == 2: mesh = create_unit_square(MPI.COMM_WORLD, 4, 4) elif dim == 3: mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2) V = FunctionSpace(mesh, ("N1curl", order)) u = Function(V) x = ufl.SpatialCoordinate(mesh) # The expression (x,y,z) is contained in the N1curl function space # order>1 f_ex = x f = Expression(f_ex, V.element.interpolation_points) u.interpolate(f) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(u - f_ex, u - f_ex) * ufl.dx))), 0) # The target expression is also contained in N2curl space of any # order V2 = FunctionSpace(mesh, ("N2curl", 1)) w = Function(V2) f2 = Expression(f_ex, V2.element.interpolation_points) w.interpolate(f2) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(w - f_ex, w - f_ex) * ufl.dx))), 0)
def test_de_rahm_2D(order): mesh = create_unit_square(MPI.COMM_WORLD, 3, 4) W = FunctionSpace(mesh, ("Lagrange", order)) w = Function(W) w.interpolate(lambda x: x[0] + x[0] * x[1] + 2 * x[1]**2) g = ufl.grad(w) Q = FunctionSpace(mesh, ("N2curl", order - 1)) q = Function(Q) q.interpolate(Expression(g, Q.element.interpolation_points)) x = ufl.SpatialCoordinate(mesh) g_ex = ufl.as_vector((1 + x[1], 4 * x[1] + x[0])) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(q - g_ex, q - g_ex) * ufl.dx))), 0) V = FunctionSpace(mesh, ("BDM", order - 1)) v = Function(V) def curl2D(u): return ufl.as_vector((ufl.Dx(u[1], 0), -ufl.Dx(u[0], 1))) v.interpolate( Expression(curl2D(ufl.grad(w)), V.element.interpolation_points)) h_ex = ufl.as_vector((1, -1)) assert np.isclose( np.abs(assemble_scalar(form(ufl.inner(v - h_ex, v - h_ex) * ufl.dx))), 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_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_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 assemble_div_matrix(k, offset): mesh = create_quad_mesh(offset) V = FunctionSpace(mesh, ("DQ", k)) W = FunctionSpace(mesh, ("RTCF", k + 1)) u, w = ufl.TrialFunction(V), ufl.TestFunction(W) a = form(ufl.inner(u, ufl.div(w)) * ufl.dx) A = assemble_matrix(a) A.assemble() return A[:, :]
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_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_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_vtx_different_meshes_function(tempdir, dim, simplex): "Test saving first order Lagrange functions" from dolfinx.cpp.io import VTXWriter mesh = generate_mesh(dim, simplex) v = Function(FunctionSpace(mesh, ("Lagrange", 1))) mesh2 = generate_mesh(dim, simplex) w = Function(FunctionSpace(mesh2, ("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_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_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_gradient(mesh): """Test discrete gradient computation (typically used for curl-curl AMG preconditioners""" V = FunctionSpace(mesh, ("Lagrange", 1)) W = FunctionSpace(mesh, ("Nedelec 1st kind H(curl)", 1)) G = create_discrete_gradient(W._cpp_object, V._cpp_object) assert G.getRefCount() == 1 num_edges = mesh.topology.index_map(1).size_global m, n = G.getSize() assert m == num_edges assert n == mesh.topology.index_map(0).size_global assert np.isclose(G.norm(PETSc.NormType.FROBENIUS), np.sqrt(2.0 * num_edges))
def rigid_motions_nullspace(V: _fem.FunctionSpace): """ Function to build nullspace for 2D/3D elasticity. Parameters: =========== V The function space """ _x = _fem.Function(V) # Get geometric dim gdim = V.mesh.geometry.dim assert gdim == 2 or gdim == 3 # Set dimension of nullspace dim = 3 if gdim == 2 else 6 # Create list of vectors for null space nullspace_basis = [_x.vector.copy() for _ in range(dim)] with ExitStack() as stack: vec_local = [stack.enter_context(x.localForm()) for x in nullspace_basis] basis = [np.asarray(x) for x in vec_local] dofs = [V.sub(i).dofmap.list.array for i in range(gdim)] # Build translational null space basis for i in range(gdim): basis[i][dofs[i]] = 1.0 # Build rotational null space basis x = V.tabulate_dof_coordinates() dofs_block = V.dofmap.list.array x0, x1, x2 = x[dofs_block, 0], x[dofs_block, 1], x[dofs_block, 2] if gdim == 2: basis[2][dofs[0]] = -x1 basis[2][dofs[1]] = x0 elif gdim == 3: basis[3][dofs[0]] = -x1 basis[3][dofs[1]] = x0 basis[4][dofs[0]] = x2 basis[4][dofs[2]] = -x0 basis[5][dofs[2]] = x1 basis[5][dofs[1]] = -x2 _la.orthonormalize(nullspace_basis) assert _la.is_orthonormal(nullspace_basis) return PETSc.NullSpace().create(vectors=nullspace_basis)
def _(V: fem.FunctionSpace, entities=None): """Creates a vtk mesh topology (topology array and array of cell types) that is based on degree of freedom coordinate. Note that this function supports Lagrange elements (continuous and discontinuous) only. """ family = V.ufl_element().family() if not (family in ['Discontinuous Lagrange', "Lagrange", "DQ", "Q"]): raise RuntimeError( "Can only create meshes from Continuous or Discontinuous function-spaces" ) if V.ufl_element().degree() == 0: raise RuntimeError("Cannot create topology from cellwise constants.") mesh = V.mesh if entities is None: num_cells = mesh.topology.index_map(mesh.topology.dim).size_local entities = np.arange(num_cells, dtype=np.int32) else: num_cells = entities.size dofmap = V.dofmap num_dofs_per_cell = V.dofmap.dof_layout.num_dofs degree = V.ufl_element().degree() cell_type = mesh.topology.cell_type if family == "Discontinuous Lagrange": perm = np.array(_perm_dg[cell_type][degree], dtype=np.int32) elif family == "DQ": perm = np.array(_perm_dq[cell_type][degree], dtype=np.int32) else: perm = np.argsort(cpp.io.perm_vtk(cell_type, num_dofs_per_cell)) if degree == 1: cell_types = np.full(num_cells, _first_order_vtk[mesh.topology.cell_type]) else: warnings.warn("Plotting of higher order functions is experimental.") cell_types = np.full(num_cells, cpp.io.get_vtk_cell_type(mesh, mesh.topology.dim)) topology = np.zeros((num_cells, num_dofs_per_cell + 1), dtype=np.int32) topology[:, 0] = num_dofs_per_cell dofmap_ = dofmap.list.array.reshape(dofmap.list.num_nodes, num_dofs_per_cell) topology[:, 1:] = dofmap_[:num_cells, perm] return topology.reshape(1, -1)[0], cell_types
def test_create_matrix_csr(): """Test creation of CSR matrix with specified types""" mesh = create_unit_square(MPI.COMM_WORLD, 10, 11) V = FunctionSpace(mesh, ("Lagrange", 1)) map = V.dofmap.index_map bs = V.dofmap.index_map_bs pattern = _cpp.la.SparsityPattern(mesh.comm, [map, map], [bs, bs]) rows = range(0, bs * map.size_local) cols = range(0, bs * map.size_local) pattern.insert(rows, cols) pattern.assemble() A = la.matrix_csr(pattern) assert A.data.dtype == np.float64 A = la.matrix_csr(pattern, dtype=np.float64) assert A.data.dtype == np.float64 A = la.matrix_csr(pattern, dtype=np.float32) assert A.data.dtype == np.float32 A = la.matrix_csr(pattern, dtype=np.complex128) assert A.data.dtype == np.complex128 cmap = pattern.column_index_map() num_cols = cmap.size_local + cmap.num_ghosts num_rows = bs * (map.size_local + map.num_ghosts) zero = np.zeros((num_rows, bs * num_cols), dtype=np.complex128) assert np.allclose(A.to_dense(), zero)
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_gradient(mesh): """Test discrete gradient computation for lowest order elements.""" V = FunctionSpace(mesh, ("Lagrange", 1)) W = FunctionSpace(mesh, ("Nedelec 1st kind H(curl)", 1)) G = create_discrete_gradient(V._cpp_object, W._cpp_object) assert G.getRefCount() == 1 num_edges = mesh.topology.index_map(1).size_global m, n = G.getSize() assert m == num_edges assert n == mesh.topology.index_map(0).size_global G.assemble() assert np.isclose(G.norm(PETSc.NormType.FROBENIUS), np.sqrt(2.0 * num_edges))
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_krylov_solver_lu(): mesh = create_unit_square(MPI.COMM_WORLD, 12, 12) V = FunctionSpace(mesh, ("Lagrange", 1)) u, v = TrialFunction(V), TestFunction(V) a = form(inner(u, v) * dx) L = form(inner(1.0, v) * dx) A = assemble_matrix(a) A.assemble() b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) norm = 13.0 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) # *Tight* tolerance for LU solves assert x.norm(PETSc.NormType.N2) == pytest.approx(norm, abs=1.0e-12)
def test_higher_order_coordinate_map(points, celltype, order): """Computes physical coordinates of a cell, based on the coordinate map.""" 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", 2)) 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]) if mesh.geometry.dim == 3: assert np.allclose(x[:, 2], 3 * X[:, 2])
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_linear_pde(): """Test Newton solver for a linear PDE""" # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 12, 12) V = FunctionSpace(mesh, ("Lagrange", 1)) u = Function(V) v = TestFunction(V) F = inner(10.0, v) * dx - inner(grad(u), grad(v)) * dx bc = dirichletbc(PETSc.ScalarType(1.0), locate_dofs_geometrical(V, lambda x: np.logical_or(np.isclose(x[0], 0.0), np.isclose(x[0], 1.0))), V) # Create nonlinear problem problem = NonlinearPDEProblem(F, u, bc) # Create Newton solver and solve solver = _cpp.nls.NewtonSolver(MPI.COMM_WORLD) solver.setF(problem.F, problem.vector()) solver.setJ(problem.J, problem.matrix()) solver.set_form(problem.form) n, converged = solver.solve(u.vector) assert converged assert n == 1 # Increment boundary condition and solve again bc.g.value[...] = PETSc.ScalarType(2.0) n, converged = solver.solve(u.vector) assert converged assert n == 1
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_mixed_element_vector_element_form(cell_type, sign, order): if cell_type == CellType.triangle or cell_type == CellType.quadrilateral: mesh = create_unit_square(MPI.COMM_WORLD, 2, 2, cell_type) else: mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2, cell_type) if cell_type == CellType.triangle: U_el = MixedElement([VectorElement("Lagrange", ufl.triangle, order), FiniteElement("N1curl", ufl.triangle, order)]) elif cell_type == CellType.quadrilateral: U_el = MixedElement([VectorElement("Lagrange", ufl.quadrilateral, order), FiniteElement("RTCE", ufl.quadrilateral, order)]) elif cell_type == CellType.tetrahedron: U_el = MixedElement([VectorElement("Lagrange", ufl.tetrahedron, order), FiniteElement("N1curl", ufl.tetrahedron, order)]) elif cell_type == CellType.hexahedron: U_el = MixedElement([VectorElement("Lagrange", ufl.hexahedron, order), FiniteElement("NCE", ufl.hexahedron, order)]) U = FunctionSpace(mesh, U_el) u, p = ufl.TrialFunctions(U) v, q = ufl.TestFunctions(U) f = form(inner(u, v) * ufl.dx + inner(p, q)(sign) * ufl.dS) A = dolfinx.fem.assemble_matrix(f) A.assemble() check_symmetry(A)
def test_ghost_mesh_assembly(mode, dx, ds): mesh = UnitSquareMesh(MPI.COMM_WORLD, 12, 12, ghost_mode=mode) V = FunctionSpace(mesh, ("Lagrange", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) dx = dx(mesh) ds = ds(mesh) f = Function(V) with f.vector.localForm() as f_local: f_local.set(10.0) a = inner(f * u, v) * dx + inner(u, v) * ds L = inner(f, v) * dx + inner(2.0, v) * ds # Initial assembly A = fem.assemble_matrix(a) A.assemble() assert isinstance(A, PETSc.Mat) b = fem.assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) assert isinstance(b, PETSc.Vec) # Check that the norms are the same for all three modes normA = A.norm() assert normA == pytest.approx(0.6713621455570528, rel=1.e-6, abs=1.e-12) normb = b.norm() assert normb == pytest.approx(1.582294032953906, rel=1.e-6, abs=1.e-12)
def test_P_simplex_built_in(family, degree, cell_type, datadir): if cell_type == CellType.tetrahedron: mesh = create_unit_cube(MPI.COMM_WORLD, 5, 5, 5) elif cell_type == CellType.triangle: mesh = create_unit_square(MPI.COMM_WORLD, 5, 5) V = FunctionSpace(mesh, (family, degree)) run_scalar_test(mesh, V, degree)
def test_nonlinear_pde(): """Test Newton solver for a simple nonlinear PDE""" # Create mesh and function space mesh = create_unit_square(MPI.COMM_WORLD, 12, 5) 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 bc = dirichletbc( PETSc.ScalarType(1.0), locate_dofs_geometrical( V, lambda x: np.logical_or(np.isclose(x[0], 0.0), np.isclose(x[0], 1.0))), V) # Create nonlinear problem problem = NonlinearPDEProblem(F, u, bc) # Create Newton solver and solve u.x.array[:] = 0.9 solver = _cpp.nls.petsc.NewtonSolver(MPI.COMM_WORLD) solver.setF(problem.F, problem.vector()) solver.setJ(problem.J, problem.matrix()) solver.set_form(problem.form) n, converged = solver.solve(u.vector) assert converged assert n < 6 # Modify boundary condition and solve again bc.g.value[...] = 0.5 n, converged = solver.solve(u.vector) assert converged assert n > 0 and n < 6