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 solve(dtype=np.float32): """Solve the variational problem""" # Process forms. This will compile the forms for the requested type. a0 = fem.form(a, dtype=dtype) if np.issubdtype(dtype, np.complexfloating): L0 = fem.form(L, dtype=dtype) else: L0 = fem.form(ufl.replace(L, {fc: 0, gc: 0}), dtype=dtype) # Create a Dirichlet boundary condition bc = fem.dirichletbc(value=dtype(0), dofs=dofs, V=V) # Assemble forms A = fem.assemble_matrix(a0, [bc]) A.finalize() b = fem.assemble_vector(L0) fem.apply_lifting(b.array, [a0], bcs=[[bc]]) b.scatter_reverse(common.ScatterMode.add) fem.set_bc(b.array, [bc]) # Create a Scipy sparse matrix that shares data with A As = scipy.sparse.csr_matrix((A.data, A.indices, A.indptr)) # Solve the variational problem and return the solution uh = fem.Function(V, dtype=dtype) uh.x.array[:] = scipy.sparse.linalg.spsolve(As, b.array) return uh
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_ghost_mesh_assembly(mode, dx, 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) dx = dx(mesh) ds = ds(mesh) f = Function(V) f.x.array[:] = 10.0 a = form(inner(f * u, v) * dx + inner(u, v) * ds) L = form(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_assemble_derivatives(): """This test checks the original_coefficient_positions, which may change under differentiation (some coefficients and constants are eliminated)""" mesh = create_unit_square(MPI.COMM_WORLD, 12, 12) Q = FunctionSpace(mesh, ("Lagrange", 1)) u = Function(Q) v = ufl.TestFunction(Q) du = ufl.TrialFunction(Q) b = Function(Q) c1 = Constant(mesh, np.array([[1.0, 0.0], [3.0, 4.0]], PETSc.ScalarType)) c2 = Constant(mesh, PETSc.ScalarType(2.0)) b.x.array[:] = 2.0 # derivative eliminates 'u' and 'c1' L = ufl.inner(c1, c1) * v * dx + c2 * b * inner(u, v) * dx a = form(derivative(L, u, du)) A1 = assemble_matrix(a) A1.assemble() a = form(c2 * b * inner(du, v) * dx) A2 = assemble_matrix(a) A2.assemble() assert (A1 - A2).norm() == pytest.approx(0.0, rel=1e-12, abs=1e-12)
def 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_vector_types(): """Assemble form using different types""" mesh = create_unit_square(MPI.COMM_WORLD, 3, 5) V = FunctionSpace(mesh, ("Lagrange", 3)) v = ufl.TestFunction(V) c = Constant(mesh, np.float64(1)) L = inner(c, v) * ufl.dx x0 = _cpp.la.Vector_float64(V.dofmap.index_map, V.dofmap.index_map_bs) L = form(L, dtype=x0.array.dtype) c0 = pack_constants(L) c1 = pack_coefficients(L) _cpp.fem.assemble_vector(x0.array, L, c0, c1) x0.scatter_reverse(_cpp.common.ScatterMode.add) c = Constant(mesh, np.complex128(1)) L = inner(c, v) * ufl.dx x1 = _cpp.la.Vector_complex128(V.dofmap.index_map, V.dofmap.index_map_bs) L = form(L, dtype=x1.array.dtype) c0 = pack_constants(L) c1 = pack_coefficients(L) _cpp.fem.assemble_vector(x1.array, L, c0, c1) x1.scatter_reverse(_cpp.common.ScatterMode.add) c = Constant(mesh, np.float32(1)) L = inner(c, v) * ufl.dx x2 = _cpp.la.Vector_float32(V.dofmap.index_map, V.dofmap.index_map_bs) L = form(L, dtype=x2.array.dtype) c0 = pack_constants(L) c1 = pack_coefficients(L) _cpp.fem.assemble_vector(x2.array, L, c0, c1) x2.scatter_reverse(_cpp.common.ScatterMode.add) assert np.linalg.norm(x0.array - x1.array) == pytest.approx(0.0) assert np.linalg.norm(x0.array - x2.array) == pytest.approx(0.0, abs=1e-8)
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_basic_assembly_constant(mode): """Tests assembly with Constant The following test should be sensitive to order of flattening the matrix-valued constant. """ mesh = create_unit_square(MPI.COMM_WORLD, 5, 5, ghost_mode=mode) V = FunctionSpace(mesh, ("Lagrange", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) c = Constant(mesh, np.array([[1.0, 2.0], [5.0, 3.0]], PETSc.ScalarType)) a = inner(c[1, 0] * u, v) * dx + inner(c[1, 0] * u, v) * ds L = inner(c[1, 0], v) * dx + inner(c[1, 0], v) * ds a, L = form(a), form(L) # Initial assembly A1 = assemble_matrix(a) A1.assemble() b1 = assemble_vector(L) b1.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) c.value = [[1.0, 2.0], [3.0, 4.0]] A2 = assemble_matrix(a) A2.assemble() b2 = assemble_vector(L) b2.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) assert (A1 * 3.0 - A2 * 5.0).norm() == pytest.approx(0.0) assert (b1 * 3.0 - b2 * 5.0).norm() == pytest.approx(0.0)
def test_assemble_manifold(): """Test assembly of poisson problem on a mesh with topological dimension 1 but embedded in 2D (gdim=2)""" points = np.array([[0.0, 0.0], [0.2, 0.0], [0.4, 0.0], [0.6, 0.0], [0.8, 0.0], [1.0, 0.0]], dtype=np.float64) cells = np.array([[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]], dtype=np.int32) cell = ufl.Cell("interval", geometric_dimension=points.shape[1]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 1)) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) assert mesh.geometry.dim == 2 assert mesh.topology.dim == 1 U = FunctionSpace(mesh, ("P", 1)) u, v = ufl.TrialFunction(U), ufl.TestFunction(U) a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx(mesh) L = ufl.inner(1.0, v) * ufl.dx(mesh) a, L = form(a), form(L) bcdofs = locate_dofs_geometrical(U, lambda x: np.isclose(x[0], 0.0)) bcs = [dirichletbc(PETSc.ScalarType(0), bcdofs, U)] A = assemble_matrix(a, bcs=bcs) A.assemble() b = assemble_vector(L) apply_lifting(b, [a], bcs=[bcs]) set_bc(b, bcs) assert np.isclose(b.norm(), 0.41231) assert np.isclose(A.norm(), 25.0199)
def test_assembly_bcs(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 L = inner(1.0, v) * dx a, L = form(a), form(L) bdofsV = locate_dofs_geometrical(V, lambda x: np.logical_or(np.isclose(x[0], 0.0), np.isclose(x[0], 1.0))) bc = dirichletbc(PETSc.ScalarType(1), bdofsV, V) # Assemble and apply 'global' lifting of bcs A = assemble_matrix(a) A.assemble() b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) g = b.duplicate() with g.localForm() as g_local: g_local.set(0.0) set_bc(g, [bc]) f = b - A * g set_bc(f, [bc]) # Assemble vector and apply lifting of bcs during assembly b_bc = assemble_vector(L) apply_lifting(b_bc, [a], [[bc]]) b_bc.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b_bc, [bc]) assert (f - b_bc).norm() == pytest.approx(0.0, rel=1e-12, abs=1e-12)
def test_pack_coefficients(): """Test packing of form coefficients ahead of main assembly call""" mesh = create_unit_square(MPI.COMM_WORLD, 12, 15) V = FunctionSpace(mesh, ("Lagrange", 1)) # Non-blocked u = Function(V) v = ufl.TestFunction(V) c = Constant(mesh, PETSc.ScalarType(12.0)) F = ufl.inner(c, v) * dx - c * ufl.sqrt(u * u) * ufl.inner(u, v) * dx u.x.array[:] = 10.0 _F = form(F) # -- Test vector b0 = assemble_vector(_F) b0.assemble() constants = pack_constants(_F) coeffs = pack_coefficients(_F) with b0.localForm() as _b0: for c in [(None, None), (None, coeffs), (constants, None), (constants, coeffs)]: b = assemble_vector(_F, coeffs=c) b.assemble() with b.localForm() as _b: assert (_b0.array_r == _b.array_r).all() # Change coefficients constants *= 5.0 for coeff in coeffs.values(): coeff *= 5.0 with b0.localForm() as _b0: for c in [(None, coeffs), (constants, None), (constants, coeffs)]: b = assemble_vector(_F, coeffs=c) b.assemble() with b.localForm() as _b: assert (_b0 - _b).norm() > 1.0e-5 # -- Test matrix du = ufl.TrialFunction(V) J = ufl.derivative(F, u, du) J = form(J) A0 = assemble_matrix(J) A0.assemble() constants = pack_constants(J) coeffs = pack_coefficients(J) for c in [(None, None), (None, coeffs), (constants, None), (constants, coeffs)]: A = assemble_matrix(J, coeffs=c) A.assemble() assert pytest.approx((A - A0).norm(), 1.0e-12) == 0.0 # Change coefficients constants *= 5.0 for coeff in coeffs.values(): coeff *= 5.0 for c in [(None, coeffs), (constants, None), (constants, coeffs)]: A = assemble_matrix(J, coeffs=c) A.assemble() assert (A - A0).norm() > 1.0e-5
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 monolithic_solve(): """Monolithic (interleaved) solver""" P2_el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2) P1_el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1) TH = P2_el * P1_el W = FunctionSpace(mesh, TH) (u, p) = ufl.TrialFunctions(W) (v, q) = ufl.TestFunctions(W) a00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx a01 = ufl.inner(p, ufl.div(v)) * dx a10 = ufl.inner(ufl.div(u), q) * dx a = a00 + a01 + a10 p00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx p11 = ufl.inner(p, q) * dx p_form = p00 + p11 f = Function(W.sub(0).collapse()[0]) p_zero = Function(W.sub(1).collapse()[0]) L0 = inner(f, v) * dx L1 = inner(p_zero, q) * dx L = L0 + L1 a, p_form, L = form(a), form(p_form), form(L) bdofsW0_P2_0 = locate_dofs_topological(W.sub(0), facetdim, bndry_facets0) bdofsW0_P2_1 = locate_dofs_topological(W.sub(0), facetdim, bndry_facets1) bc0 = dirichletbc(bc_value, bdofsW0_P2_0, W.sub(0)) bc1 = dirichletbc(bc_value, bdofsW0_P2_1, W.sub(0)) A = assemble_matrix(a, bcs=[bc0, bc1]) A.assemble() P = assemble_matrix(p_form, bcs=[bc0, bc1]) P.assemble() b = assemble_vector(L) apply_lifting(b, [a], bcs=[[bc0, bc1]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc0, bc1]) ksp = PETSc.KSP() ksp.create(mesh.comm) ksp.setOperators(A, P) ksp.setType("minres") pc = ksp.getPC() pc.setType('lu') def monitor(ksp, its, rnorm): # print("Num it, rnorm:", its, rnorm) pass ksp.setTolerances(rtol=1.0e-8, max_it=50) ksp.setMonitor(monitor) ksp.setFromOptions() x = A.createVecRight() ksp.solve(b, x) assert ksp.getConvergedReason() > 0 return b.norm(), x.norm(), A.norm(), P.norm()
def __init__(self, F, u, bc): V = u.function_space du = TrialFunction(V) self.L = form(F) self.a = form(derivative(F, u, du)) self.bc = bc self._F, self._J = None, None self.u = u
def test_assemble_empty_rank_mesh(): """Assembly on mesh where some ranks are empty""" comm = MPI.COMM_WORLD cell_type = CellType.triangle domain = ufl.Mesh( ufl.VectorElement("Lagrange", ufl.Cell(cell_type.name), 1)) def partitioner(comm, nparts, local_graph, num_ghost_nodes, ghosting): """Leave cells on the curent rank""" dest = np.full(len(cells), comm.rank, dtype=np.int32) return graph.create_adjacencylist(dest) if comm.rank == 0: # Put cells on rank 0 cells = np.array([[0, 1, 2], [0, 2, 3]], dtype=np.int64) cells = graph.create_adjacencylist(cells) x = np.array([[0., 0.], [1., 0.], [1., 1.], [0., 1.]]) else: # No cells onm other ranks cells = graph.create_adjacencylist(np.empty((0, 3), dtype=np.int64)) x = np.empty((0, 2), dtype=np.float64) mesh = create_mesh(comm, cells, x, domain, GhostMode.none, partitioner) V = FunctionSpace(mesh, ("Lagrange", 2)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) f, k, zero = Function(V), Function(V), Function(V) f.x.array[:] = 10.0 k.x.array[:] = 1.0 zero.x.array[:] = 0.0 a = form(inner(k * u, v) * dx + inner(zero * u, v) * ds) L = form(inner(f, v) * dx + inner(zero, v) * ds) M = form(2 * k * dx + k * ds) sum = comm.allreduce(assemble_scalar(M), op=MPI.SUM) assert sum == pytest.approx(6.0) # Assemble A = assemble_matrix(a) A.assemble() b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) # Solve ksp = PETSc.KSP() ksp.create(mesh.comm) ksp.setOperators(A) ksp.setTolerances(rtol=1.0e-9, max_it=50) ksp.setFromOptions() x = b.copy() ksp.solve(b, x) assert np.allclose(x.array, 10.0)
def test_assemble_functional_dx(mode): mesh = create_unit_square(MPI.COMM_WORLD, 12, 12, ghost_mode=mode) M = form(1.0 * dx(domain=mesh)) value = assemble_scalar(M) value = mesh.comm.allreduce(value, op=MPI.SUM) assert value == pytest.approx(1.0, 1e-12) x = ufl.SpatialCoordinate(mesh) M = form(x[0] * dx(domain=mesh)) value = assemble_scalar(M) value = mesh.comm.allreduce(value, op=MPI.SUM) assert value == pytest.approx(0.5, 1e-12)
def test_facet_area1D(): mesh = create_unit_interval(MPI.COMM_WORLD, 10) # NOTE: Area of a vertex is defined to 1 in ufl c0 = ufl.FacetArea(mesh) c = Constant(mesh, ScalarType(1)) ds = ufl.Measure("ds", domain=mesh) a0 = mesh.comm.allreduce(assemble_scalar(form(c * ds)), op=MPI.SUM) a = mesh.comm.allreduce(assemble_scalar(form(c0 * ds)), op=MPI.SUM) assert numpy.isclose(a.real, 2) assert numpy.isclose(a0.real, 2)
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_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_assembly_dS_domains(mode): N = 10 mesh = create_unit_square(MPI.COMM_WORLD, N, N, ghost_mode=mode) one = Constant(mesh, PETSc.ScalarType(1)) val = assemble_scalar(form(one * ufl.dS)) val = mesh.comm.allreduce(val, op=MPI.SUM) assert val == pytest.approx(2 * (N - 1) + N * np.sqrt(2), 1.0e-7)
def test_lambda_assembler(): """Tests assembly with a lambda function""" mesh = create_unit_square(MPI.COMM_WORLD, 5, 5) V = FunctionSpace(mesh, ("Lagrange", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = inner(u, v) * dx # Initial assembly a_form = form(a) rdata = [] cdata = [] vdata = [] def mat_insert(rows, cols, vals): vdata.append(vals) rdata.append(np.repeat(rows, len(cols))) cdata.append(np.tile(cols, len(rows))) return 0 _cpp.fem.assemble_matrix(mat_insert, a_form, []) vdata = np.array(vdata).flatten() cdata = np.array(cdata).flatten() rdata = np.array(rdata).flatten() mat = scipy.sparse.coo_matrix((vdata, (rdata, cdata))) v = np.ones(mat.shape[1]) s = MPI.COMM_WORLD.allreduce(mat.dot(v).sum(), MPI.SUM) assert np.isclose(s, 1.0)
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_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_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 assemble_div_vector(k, offset): mesh = create_quad_mesh(offset) V = FunctionSpace(mesh, ("RTCF", k + 1)) v = ufl.TestFunction(V) L = form( ufl.inner(Constant(mesh, PETSc.ScalarType(1)), ufl.div(v)) * ufl.dx) b = assemble_vector(L) return b[:]
def test_facet_area(mesh_factory): """ Compute facet area of cell. UFL currently only supports affine cells for this computation """ # NOTE: UFL only supports facet area calculations of affine cells func, args, exact_area = mesh_factory mesh = func(*args) c0 = ufl.FacetArea(mesh) c = Constant(mesh, ScalarType(1)) tdim = mesh.topology.dim num_faces = 4 if tdim == 2 else 6 ds = ufl.Measure("ds", domain=mesh) a = mesh.comm.allreduce(assemble_scalar(form(c * ds)), op=MPI.SUM) a0 = mesh.comm.allreduce(assemble_scalar(form(c0 * ds)), op=MPI.SUM) assert numpy.isclose(a.real, num_faces) assert numpy.isclose(a0.real, num_faces * exact_area)
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_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)