def test_contains_h1(): h1_elements = [ # Standard Lagrange elements: FiniteElement("CG", triangle, 1), FiniteElement("CG", triangle, 2), # Some special elements: FiniteElement("HER", triangle), FiniteElement("MTW", triangle), # Tensor product elements: TensorProductElement(FiniteElement("CG", interval, 1), FiniteElement("CG", interval, 1)), TensorProductElement(FiniteElement("CG", interval, 2), FiniteElement("CG", interval, 2)), # Enriched elements: EnrichedElement(FiniteElement("CG", triangle, 2), FiniteElement("B", triangle, 3)) ] for h1_element in h1_elements: assert h1_element in H1 assert h1_element in H1dx1dy assert h1_element in HDiv assert h1_element in HCurl assert h1_element in L2 assert h1_element in H0dx0dy assert h1_element not in H2 assert h1_element not in H2dx2dy
def test_physically_mapped_facet(): mesh = Mesh(VectorElement("P", triangle, 1)) # set up variational problem U = FiniteElement("Morley", mesh.ufl_cell(), 2) V = FiniteElement("P", mesh.ufl_cell(), 1) R = FiniteElement("P", mesh.ufl_cell(), 1) Vv = VectorElement(BrokenElement(V)) Qhat = VectorElement(BrokenElement(V[facet])) Vhat = VectorElement(V[facet]) Z = FunctionSpace(mesh, MixedElement(U, Vv, Qhat, Vhat, R)) z = Coefficient(Z) u, d, qhat, dhat, lam = split(z) s = FacetNormal(mesh) trans = as_matrix([[1, 0], [0, 1]]) mat = trans*grad(grad(u))*trans + outer(d, d) * u J = (u**2*dx + u**3*dx + u**4*dx + inner(mat, mat)*dx + inner(grad(d), grad(d))*dx + dot(s, d)**2*ds) L_match = inner(qhat, dhat - d) L = J + inner(lam, inner(d, d)-1)*dx + (L_match('+') + L_match('-'))*dS + L_match*ds compile_form(L)
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 initialize_data(self): """ Extract required objects for defining error control forms. This will be stored, reused and in particular named. """ # Developer's note: The UFL-FFC-DOLFIN--PyDOLFIN toolchain for # error control is quite fine-tuned. In particular, the order # of coefficients in forms is (and almost must be) used for # their assignment. This means that the order in which these # coefficients are defined matters and should be considered # fixed. from ufl import FiniteElement, Coefficient from ufl.algorithms.elementtransformations import tear, increase_order # Primal trial element space self._V = self.u.element() # Primal test space == Dual trial space Vhat = self.weak_residual.arguments()[0].element() # Discontinuous version of primal trial element space self._dV = tear(self._V) # Extract domain and geometric dimension domain, = self._V.domains() gdim = domain.geometric_dimension() # Coefficient representing improved dual E = increase_order(Vhat) self._Ez_h = Coefficient(E) self.ec_names[id(self._Ez_h)] = "__improved_dual" # Coefficient representing cell bubble function B = FiniteElement("B", domain, gdim + 1) self._b_T = Coefficient(B) self.ec_names[id(self._b_T)] = "__cell_bubble" # Coefficient representing strong cell residual self._R_T = Coefficient(self._dV) self.ec_names[id(self._R_T)] = "__cell_residual" # Coefficient representing cell cone function C = FiniteElement("DG", domain, gdim) self._b_e = Coefficient(C) self.ec_names[id(self._b_e)] = "__cell_cone" # Coefficient representing strong facet residual self._R_dT = Coefficient(self._dV) self.ec_names[id(self._R_dT)] = "__facet_residual" # Define discrete dual on primal test space self._z_h = Coefficient(Vhat) self.ec_names[id(self._z_h)] = "__discrete_dual_solution" # Piecewise constants for assembling indicators self._DG0 = FiniteElement("DG", domain, 0)
def test_mini(): m = Mesh(VectorElement('CG', triangle, 1)) P1 = FiniteElement('Lagrange', triangle, 1) B = FiniteElement("Bubble", triangle, 3) V = FunctionSpace(m, VectorElement(P1 + B)) u = TrialFunction(V) v = TestFunction(V) a = inner(grad(u), grad(v)) * dx count_flops(a)
def lower_element_order(elem): if isinstance(elem, VectorElement): ndofs = elem.value_size() baseelem = lower_element_order(elem.sub_elements()[0]) return VectorElement(baseelem, dim=ndofs) elif isinstance(elem, MixedElement): # must come after because VectorElement is a subclass of MixedElement! elemlist = elem.sub_elements() newelemlist = [] for subelem in elemlist: newelemlist.append(lower_element_order(subelem)) return newelemlist if isinstance(elem, EnrichedElement): elem1, elem2 = elem._elements if (isinstance(elem1, HDivElement) and isinstance(elem2, HDivElement)): elem1 = elem1._element elem2 = elem2._element elem1low = lower_element_order(elem1) elem2low = lower_element_order(elem2) return HDivElement(elem1low) + HDivElement(elem2low) if (isinstance(elem1, HCurlElement) and isinstance(elem2, HCurlElement)): elem1 = elem1._element elem2 = elem2._element elem1low = lower_element_order(elem1) elem2low = lower_element_order(elem2) return HCurlElement(elem1low) + HCurlElement(elem2low) elif isinstance(elem, TensorProductElement): elem1, elem2 = elem.sub_elements() elem1low = lower_element_order(elem1) elem2low = lower_element_order(elem2) return TensorProductElement(elem1low, elem2low) elif isinstance(elem, FiniteElement): if elem.cell().cellname() == 'interval': if elem.family() == 'Discontinuous Lagrange': return FiniteElement("DG", interval, 0, variant='mgd') elif elem.family() == 'Lagrange': return FiniteElement("CG", interval, 1, variant='mgd') elif elem.cell().cellname() == 'quadrilateral': if elem.family() == 'Q': return FiniteElement("Q", quadrilateral, 1, variant='mgd') if elem.family() == 'DQ': return FiniteElement("DQ", quadrilateral, 0, variant='mgd') if elem.family() == 'RTCF': return FiniteElement("RTCF", quadrilateral, 1, variant='mgd') if elem.family() == 'RTCE': return FiniteElement("RTCE", quadrilateral, 1, variant='mgd') elif elem.cell().cellname() == 'hexahedron': if elem.family() == 'Q': return FiniteElement("Q", hexahedron, 1, variant='mgd') if elem.family() == 'DQ': return FiniteElement("DQ", hexahedron, 0, variant='mgd') if elem.family() == 'NCF': return FiniteElement("NCF", hexahedron, 1, variant='mgd') if elem.family() == 'NCE': return FiniteElement("NCE", hexahedron, 1, variant='mgd')
def test_contains_hdiv(): hdiv_elements = [ FiniteElement("RT", triangle, 1), FiniteElement("BDM", triangle, 1), FiniteElement("BDFM", triangle, 2), # HDiv elements: HDiv( TensorProductElement(FiniteElement("DG", triangle, 1), FiniteElement("CG", interval, 2))), HDiv( TensorProductElement(FiniteElement("RT", triangle, 1), FiniteElement("DG", interval, 1))), HDiv( TensorProductElement(FiniteElement("N1curl", triangle, 1), FiniteElement("DG", interval, 1))) ] for hdiv_element in hdiv_elements: assert hdiv_element in HDiv assert hdiv_element in L2 assert hdiv_element in H0dx0dy assert hdiv_element not in H1 assert hdiv_element not in H1dx1dy assert hdiv_element not in HCurl assert hdiv_element not in H2 assert hdiv_element not in H2dx2dy
def test_contains_hcurl(): hcurl_elements = [ FiniteElement("N1curl", triangle, 1), FiniteElement("N2curl", triangle, 1), ] for hcurl_element in hcurl_elements: assert hcurl_element in HCurl assert hcurl_element in L2 assert hcurl_element not in H1 assert hcurl_element not in HDiv assert hcurl_element not in H2
def test_contains_h2(): h2_elements = [ FiniteElement("ARG", triangle, 1), FiniteElement("MOR", triangle), ] for h2_element in h2_elements: assert h2_element in H2 assert h2_element in H1 assert h2_element in HDiv assert h2_element in HCurl assert h2_element in L2
def test_contains_hdiv(): hdiv_elements = [ FiniteElement("RT", triangle, 1), FiniteElement("BDM", triangle, 1), FiniteElement("BDFM", triangle, 2), ] for hdiv_element in hdiv_elements: assert hdiv_element in HDiv assert hdiv_element in L2 assert hdiv_element not in H1 assert hdiv_element not in HCurl assert hdiv_element not in H2
def test_global_dof_builder(mesh_factory): func, args = mesh_factory mesh = func(*args) V = VectorElement("CG", mesh.ufl_cell(), 1) Q = FiniteElement("CG", mesh.ufl_cell(), 1) R = FiniteElement("R", mesh.ufl_cell(), 0) W = FunctionSpace(mesh, MixedElement([Q, Q, Q, R])) W = FunctionSpace(mesh, MixedElement([Q, Q, R, Q])) W = FunctionSpace(mesh, V * R) W = FunctionSpace(mesh, R * V) assert (W)
def test_contains_h2(): h2_elements = [ FiniteElement("ARG", triangle, 5), FiniteElement("MOR", triangle, 2), ] for h2_element in h2_elements: assert h2_element in H2 assert h2_element in H2dx2dy assert h2_element in H1 assert h2_element in H1dx1dy assert h2_element in HDiv assert h2_element in HCurl assert h2_element in L2 assert h2_element in H0dx0dy
def test_contains_l2(): l2_elements = [ FiniteElement("Real", triangle, 0), FiniteElement("DG", triangle, 0), FiniteElement("DG", triangle, 1), FiniteElement("DG", triangle, 2), FiniteElement("CR", triangle, 1), ] for l2_element in l2_elements: assert l2_element in L2 assert l2_element not in H1 assert l2_element not in HCurl assert l2_element not in HDiv assert l2_element not in H2
def test_extract_elements_and_extract_unique_elements(forms): b = forms[2] integrals = b.integrals_by_type("cell") integrand = integrals[0].integrand() element1 = FiniteElement("CG", triangle, 1) element2 = FiniteElement("CG", triangle, 1) v = TestFunction(element1) u = TrialFunction(element2) a = u * v * dx assert extract_elements(a) == (element1, element2) assert extract_unique_elements(a) == (element1, )
def test_taylor_hood_cube(): pytest.xfail("Problem with Mixed Function Spaces") meshc = UnitCubeMesh(MPI.comm_world, 2, 2, 2) meshf = UnitCubeMesh(MPI.comm_world, 3, 4, 5) Ve = VectorElement("CG", meshc.ufl_cell(), 2) Qe = FiniteElement("CG", meshc.ufl_cell(), 1) Ze = MixedElement([Ve, Qe]) Zc = FunctionSpace(meshc, Ze) Zf = FunctionSpace(meshf, Ze) def z(x): return np.row_stack((x[0] * x[1], x[1] * x[2], x[2] * x[0], x[0] + 3.0 * x[1] + x[2])) zc, zf = Function(Zc), Function(Zf) zc.interpolate(z) zf.interpolate(z) mat = PETScDMCollection.create_transfer_matrix(Zc, Zf) Zuc = Function(Zf) mat.mult(zc.vector, Zuc.vector) Zuc.vector.update_ghost_values() diff = Function(Zf) diff.assign(Zuc - zf) assert diff.vector.norm("l2") < 1.0e-12
def test_contains_h1(): h1_elements = [ # Standard Lagrange elements: FiniteElement("CG", triangle, 1), FiniteElement("CG", triangle, 2), # Some special elements: FiniteElement("AW", triangle), FiniteElement("HER", triangle), FiniteElement("MTW", triangle), ] for h1_element in h1_elements: assert h1_element in H1 assert h1_element in HDiv assert h1_element in HCurl assert h1_element in L2 assert h1_element not in H2
def set_cell_sizes(self, domain): """Setup a fake coefficient for "cell sizes". :arg domain: The domain of the integral. This is required for scaling of derivative basis functions on physically mapped elements (Argyris, Bell, etc...). We need a measure of the mesh size around each vertex (hence this lives in P1). Should the domain have topological dimension 0 this does nothing. """ if domain.ufl_cell().topological_dimension() > 0: # Can't create P1 since only P0 is a valid finite element if # topological_dimension is 0 and the concept of "cell size" # is not useful for a vertex. f = Coefficient( FunctionSpace(domain, FiniteElement("P", domain.ufl_cell(), 1))) funarg, expression = prepare_coefficient( f, "cell_sizes", self.scalar_type, interior_facet=self.interior_facet) self.cell_sizes_arg = funarg self._cell_sizes = expression
def test_save_and_checkpoint_timeseries(tempdir, encoding): mesh = UnitSquareMesh(MPI.comm_world, 16, 16) filename = os.path.join(tempdir, "u2_checkpoint.xdmf") FE = FiniteElement("CG", mesh.ufl_cell(), 2) V = FunctionSpace(mesh, FE) times = [0.5, 0.2, 0.1] u_out = [None] * len(times) u_in = [None] * len(times) p = 0.0 def expr_eval(values, x): values[:, 0] = x[:, 0] * p with XDMFFile(mesh.mpi_comm(), filename, encoding=encoding) as file: for i, p in enumerate(times): u_out[i] = interpolate(expr_eval, V) file.write_checkpoint(u_out[i], "u_out", p) with XDMFFile(mesh.mpi_comm(), filename) as file: for i, p in enumerate(times): u_in[i] = file.read_checkpoint(V, "u_out", i) for i, p in enumerate(times): u_in[i].vector.axpy(-1.0, u_out[i].vector) assert u_in[i].vector.norm() < 1.0e-12 # test reading last with XDMFFile(mesh.mpi_comm(), filename) as file: u_in_last = file.read_checkpoint(V, "u_out", -1) u_out[-1].vector.axpy(-1.0, u_in_last.vector) assert u_out[-1].vector.norm() < 1.0e-12
def test_taylor_hood_cube(): pytest.xfail("Problem with Mixed Function Spaces") meshc = UnitCubeMesh(MPI.comm_world, 2, 2, 2) meshf = UnitCubeMesh(MPI.comm_world, 3, 4, 5) Ve = VectorElement("CG", meshc.ufl_cell(), 2) Qe = FiniteElement("CG", meshc.ufl_cell(), 1) Ze = MixedElement([Ve, Qe]) Zc = FunctionSpace(meshc, Ze) Zf = FunctionSpace(meshf, Ze) def z(values, x): values[:, 0] = x[:, 0] * x[:, 1] values[:, 1] = x[:, 1] * x[:, 2] values[:, 2] = x[:, 2] * x[:, 0] values[:, 3] = x[:, 0] + 3.0 * x[:, 1] + x[:, 2] zc = interpolate(z, Zc) zf = interpolate(z, Zf) mat = PETScDMCollection.create_transfer_matrix(Zc, Zf) Zuc = Function(Zf) mat.mult(zc.vector, Zuc.vector) Zuc.vector.update_ghost_values() diff = Function(Zf) diff.assign(Zuc - zf) assert diff.vector.norm("l2") < 1.0e-12
def test_save_and_checkpoint_scalar(tempdir, encoding, fe_degree, fe_family, mesh_tdim, mesh_n): if invalid_fe(fe_family, fe_degree): pytest.skip("Trivial finite element") filename = os.path.join(tempdir, "u1_checkpoint.xdmf") mesh = mesh_factory(mesh_tdim, mesh_n) FE = FiniteElement(fe_family, mesh.ufl_cell(), fe_degree) V = FunctionSpace(mesh, FE) u_in = Function(V) u_out = Function(V) if has_petsc_complex: def expr_eval(values, x): values[:, 0] = x[:, 0] + 1.0j * x[:, 0] u_out.interpolate(expr_eval) else: def expr_eval(values, x): values[:, 0] = x[:, 0] u_out.interpolate(expr_eval) with XDMFFile(mesh.mpi_comm(), filename, encoding=encoding) as file: file.write_checkpoint(u_out, "u_out", 0) with XDMFFile(mesh.mpi_comm(), filename) as file: u_in = file.read_checkpoint(V, "u_out", 0) u_in.vector.axpy(-1.0, u_out.vector) assert u_in.vector.norm() < 1.0e-12
def test_tabulate_dofs(mesh_factory): func, args = mesh_factory mesh = func(*args) W0 = FiniteElement("Lagrange", mesh.ufl_cell(), 1) W1 = VectorElement("Lagrange", mesh.ufl_cell(), 1) W = FunctionSpace(mesh, W0 * W1) L0 = W.sub(0) L1 = W.sub(1) L01 = L1.sub(0) L11 = L1.sub(1) for i, cell in enumerate(Cells(mesh)): dofs0 = L0.dofmap().cell_dofs(cell.index()) dofs1 = L01.dofmap().cell_dofs(cell.index()) dofs2 = L11.dofmap().cell_dofs(cell.index()) dofs3 = L1.dofmap().cell_dofs(cell.index()) assert np.array_equal(dofs0, L0.dofmap().cell_dofs(i)) assert np.array_equal(dofs1, L01.dofmap().cell_dofs(i)) assert np.array_equal(dofs2, L11.dofmap().cell_dofs(i)) assert np.array_equal(dofs3, L1.dofmap().cell_dofs(i)) assert len(np.intersect1d(dofs0, dofs1)) == 0 assert len(np.intersect1d(dofs0, dofs2)) == 0 assert len(np.intersect1d(dofs1, dofs2)) == 0 assert np.array_equal(np.append(dofs1, dofs2), dofs3)
def mass_dg(cell, degree): m = Mesh(VectorElement('Q', cell, 1)) V = FunctionSpace(m, FiniteElement('DQ', cell, degree, variant='spectral')) u = TrialFunction(V) v = TestFunction(V) # In this case, the estimated quadrature degree will give the # correct number of quadrature points by luck. return u * v * dx
def main(args): "Call evaluate basis derivatives for a range of different elements." if "refs" in args: print_refs() return 0 # Change to temporary folder and copy form files if not os.path.isdir("tmp"): os.mkdir("tmp") os.chdir("tmp") values = {} # Evaluate basis for single elements print("\nComputing evaluate_basis_derivatives for single elements") for element in single_elements: for shape in element["shapes"]: for order in element["orders"]: ufl_element = FiniteElement(element["family"], shape, order) print("Compiling element: ", str(ufl_element)) error = compile_element(ufl_element) if error: continue print("Computing values") values[repr(ufl_element)] = {} for deriv_order in range(1, 4): values[repr(ufl_element)][deriv_order] = compute_values( ufl_element, deriv_order) # Evaluate basis for single elements print("\nComputing evaluate_basis_derivatives for mixed elements") for ufl_element in mixed_elements: print("Compiling element: ", str(ufl_element)) error = compile_element(ufl_element) if error: continue print("Computing values") values[repr(ufl_element)] = {} for deriv_order in range(1, 4): values[repr(ufl_element)][deriv_order] = compute_values( ufl_element, deriv_order) # Load or update reference values os.chdir(os.pardir) if os.path.isfile("reference.pickle"): reference = pickle.load(open("reference.pickle", "r")) else: print("Unable to find reference values, storing current values.") pickle.dump(values, open("reference.pickle", "w")) return 0 # Check results error = check_results(values, reference) if not error: # Remove temporary directory shutil.rmtree("tmp") return error
def test_tabulate_coord_periodic(mesh_factory): class PeriodicBoundary2(SubDomain): def inside(self, x, on_boundary): return x[0] < np.finfo(float).eps def map(self, x, y): y[0] = x[0] - 1.0 y[1] = x[1] # Create periodic boundary condition periodic_boundary = PeriodicBoundary2() func, args = mesh_factory mesh = func(*args) V = FiniteElement("Lagrange", mesh.ufl_cell(), 1) Q = VectorElement("Lagrange", mesh.ufl_cell(), 1) W = V * Q V = FunctionSpace(mesh, V, constrained_domain=periodic_boundary) W = FunctionSpace(mesh, W, constrained_domain=periodic_boundary) L0 = W.sub(0) L1 = W.sub(1) L01 = L1.sub(0) L11 = L1.sub(1) sdim = V.element().space_dimension() coord0 = np.zeros((sdim, 2), dtype="d") coord1 = np.zeros((sdim, 2), dtype="d") coord2 = np.zeros((sdim, 2), dtype="d") coord3 = np.zeros((sdim, 2), dtype="d") for cell in Cells(mesh): coord0 = V.element().tabulate_dof_coordinates(cell) coord1 = L0.element().tabulate_dof_coordinates(cell) coord2 = L01.element().tabulate_dof_coordinates(cell) coord3 = L11.element().tabulate_dof_coordinates(cell) coord4 = L1.element().tabulate_dof_coordinates(cell) assert (coord0 == coord1).all() assert (coord0 == coord2).all() assert (coord0 == coord3).all() assert (coord4[:sdim] == coord0).all() assert (coord4[sdim:] == coord0).all()
def test_varying_continuity_elements(): P1DG_t = FiniteElement("DG", triangle, 1) P1DG_i = FiniteElement("DG", interval, 1) P1 = FiniteElement("CG", interval, 1) P2 = FiniteElement("CG", interval, 2) P3 = FiniteElement("CG", interval, 3) RT1 = FiniteElement("RT", triangle, 1) ARG = FiniteElement("ARG", triangle, 5) # Tensor product elements P1DGP2 = TensorProductElement(P1DG_t, P2) P1P1DG = TensorProductElement(P1, P1DG_i) P1DGP1 = TensorProductElement(P1DG_i, P1) RT1DG1 = TensorProductElement(RT1, P1DG_i) P2P3 = TensorProductElement(P2, P3) ARGP3 = TensorProductElement(ARG, P3) assert P1DGP2 in H1dz and P1DGP2 in L2 assert P1DGP2 not in H1dh assert P1DGP1 in H1dy and P1DGP2 in L2 assert P1P1DG in H1dx and P1P1DG in L2 assert P1P1DG not in H1dx1dy assert RT1DG1 in H000 and RT1DG1 in L2 assert P2P3 in H1dx1dy and P2P3 in H1 assert ARG in H2dx2dy assert ARGP3 in H2dhH1dz
def test_expr(): from ufl import triangle, FiniteElement, TestFunction, TrialFunction, Coefficient element = FiniteElement("CG", triangle, 1) v = TestFunction(element) u = TrialFunction(element) f = Coefficient(element) g = Coefficient(element) expr = (f + g) * u.dx(0) * (g - 1) * v return expr
def test_cell_error(cell, degree): """Test that tabulating the trace element deliberatly on the cell triggers `gem.Failure` to raise the TraceError exception. """ trace_element = FiniteElement("HDiv Trace", cell, degree) lambdar = TrialFunction(trace_element) gammar = TestFunction(trace_element) with pytest.raises(TraceError): compile_form(lambdar * gammar * dx)
def test_compute_form_adjoint(self): cell = triangle element = FiniteElement('Lagrange', cell, 1) u = TrialFunction(element) v = TestFunction(element) a = inner(grad(u), grad(v)) * dx assert compute_form_adjoint(a) == conj(inner(grad(v), grad(u))) * dx
def test_automatic_simplification(self): cell = triangle element = FiniteElement("Lagrange", cell, 1) v = TestFunction(element) u = TrialFunction(element) assert inner(u, v) == u * conj(v) assert dot(u, v) == u * v assert outer(u, v) == conj(u) * v
def test_gradient_error(cell, degree): """Test that tabulating gradient evaluations of the trace element triggers `gem.Failure` to raise the TraceError exception. """ trace_element = FiniteElement("HDiv Trace", cell, degree) lambdar = TrialFunction(trace_element) gammar = TestFunction(trace_element) with pytest.raises(TraceError): compile_form(inner(grad(lambdar('+')), grad(gammar('+'))) * dS)