Ejemplo n.º 1
0
def test_bc_elements(elements_to_test, cells_to_test, n_tri, element_type):
    if elements_to_test != "ALL" and element_type not in elements_to_test:
        pytest.skip()
    if cells_to_test != "ALL" and "dual polygon" not in cells_to_test:
        pytest.skip()

    create_element(f"dual polygon({n_tri})", element_type, 1)
Ejemplo n.º 2
0
def plot_single_element(matches):
    if "variant=" in matches[1]:
        a, b = matches[1].split(" variant=")
        e = symfem.create_element(a, matches[2], int(matches[3]), b)
    else:
        e = symfem.create_element(matches[1], matches[2], int(matches[3]))
    return f"<center>{plotting.plot_function(e, int(matches[4]))}</center>"
Ejemplo n.º 3
0
def plot_element(matches):
    if "variant=" in matches[1]:
        a, b = matches[1].split(" variant=")
        e = symfem.create_element(a, matches[2], int(matches[3]), b)
    else:
        e = symfem.create_element(matches[1], matches[2], int(matches[3]))
    return ("<center>"
            f"{''.join([plotting.plot_function(e, i) for i in range(e.space_dim)])}"
            "</center>")
Ejemplo n.º 4
0
def test_orthogonal(cell):
    if cell == "pyramid":
        pytest.xfail("Legendre polynomials not implemented for pyramids yet.")

    if cell == "interval":
        e = create_element(cell, "Lagrange", 5)
    else:
        e = create_element(cell, "Lagrange", 2)
    basis = legendre.get_legendre_basis(e._basis, e.reference)

    for i, f in enumerate(basis):
        for g in basis[:i]:
            assert e.reference.integral(subs(f * g, x, t)) == 0
Ejemplo n.º 5
0
def test_dual_elements(elements_to_test, cells_to_test, n_tri, order):
    if elements_to_test != "ALL" and "dual" not in elements_to_test:
        pytest.skip()
    if cells_to_test != "ALL" and "dual polygon" not in cells_to_test:
        pytest.skip()

    space = create_element(f"dual polygon({n_tri})", "dual", order)
    sub_e = create_element("triangle", space.fine_space, space.order)
    for f, coeff_list in zip(space.get_basis_functions(),
                             space.dual_coefficients):
        for piece, coeffs in zip(f.pieces, coeff_list):
            map = sub_e.reference.get_map_to(piece[0])
            for dof, value in zip(sub_e.dofs, coeffs):
                point = subs(map, x, dof.point)
                assert symequal(value, subs(piece[1], x, point))
Ejemplo n.º 6
0
def test_guzman_neilan_triangle(order):
    e = symfem.create_element("triangle", "Guzman-Neilan", order)

    for p in e._basis[-3:]:
        for piece in p.pieces:
            print(div(piece[1]).expand())
            float(div(piece[1]).expand())
Ejemplo n.º 7
0
Archivo: q.py Proyecto: mscroggs/symfem
    def get_tensor_factorisation(self):
        """Get the representation of the element as a tensor product."""
        from symfem import create_element
        interval_q = create_element("interval", "Lagrange", self.order)

        if self.order == 0:
            perm = [0]
        elif self.reference.name == "quadrilateral":
            n = self.order - 1
            perm = [0, 2] + [4 + n + i for i in range(n)]
            perm += [1, 3] + [4 + 2 * n + i for i in range(n)]
            for i in range(n):
                perm += [4 + i, 4 + 3 * n + i] + [4 + i + (4 + j) * n for j in range(n)]
        elif self.reference.name == "hexahedron":
            n = self.order - 1
            perm = [0, 4] + [8 + 2 * n + i for i in range(n)]
            perm += [2, 6] + [8 + 6 * n + i for i in range(n)]
            for i in range(n):
                perm += [8 + n + i, 8 + 9 * n + i]
                perm += [8 + 12 * n + 2 * n ** 2 + i + n * j for j in range(n)]
            perm += [1, 5] + [8 + 4 * n + i for i in range(n)]
            perm += [3, 7] + [8 + 7 * n + i for i in range(n)]
            for i in range(n):
                perm += [8 + 3 * n + i, 8 + 10 * n + i]
                perm += [8 + 12 * n + 3 * n ** 2 + i + n * j for j in range(n)]
            for i in range(n):
                perm += [8 + i, 8 + 8 * n + i]
                perm += [8 + 12 * n + n ** 2 + i + n * j for j in range(n)]
                perm += [8 + 5 * n + i, 8 + 11 * n + i]
                perm += [8 + 12 * n + 4 * n ** 2 + i + n * j for j in range(n)]
                for j in range(n):
                    perm += [8 + 12 * n + i + n * j, 8 + 12 * n + 5 * n ** 2 + i + n * j]
                    perm += [8 + 12 * n + 6 * n ** 2 + i + n * j + n ** 2 * k for k in range(n)]

        return [("scalar", [interval_q for i in range(self.reference.tdim)], perm)]
Ejemplo n.º 8
0
def test_basis_continuity_triangle(order):
    N = 5
    e = symfem.create_element("triangle", "Guzman-Neilan", order)
    third = sympy.Rational(1, 3)
    one = sympy.Integer(1)
    for pt in [(0, 0), (1, 0), (0, 1), (third, third)]:
        for f in e.get_polynomial_basis():
            value = None
            for p in f.pieces:
                if pt in p[0]:
                    if value is None:
                        value = symfem.symbolic.subs(p[1], symfem.symbolic.x,
                                                     pt)
                    assert value == symfem.symbolic.subs(
                        p[1], symfem.symbolic.x, pt)
    for pts in combinations([(0, 0), (1, 0), (1, 0), (third, third)], 2):
        for i in range(N + 1):
            pt = tuple(a + (b - a) * i * one / N for a, b in zip(*pts))
            for f in e.get_polynomial_basis():
                value = None
                for p in f.pieces:
                    if pts[0] in p[0] and pts[1] in p[0]:
                        if value is None:
                            value = symfem.symbolic.subs(
                                p[1], symfem.symbolic.x, pt)
                        assert value == symfem.symbolic.subs(
                            p[1], symfem.symbolic.x, pt)
Ejemplo n.º 9
0
    def get_basis_functions(self, reshape=True, symbolic=True, use_tensor_factorisation=False):
        """Get the basis functions of the element."""
        assert not use_tensor_factorisation

        if self._basis_functions is None:
            from symfem import create_element

            self._basis_functions = []
            for coeff_list in self.dual_coefficients:
                v0 = self.reference.origin
                pieces = []
                for coeffs, v1, v2 in zip(
                    coeff_list, self.reference.vertices,
                    self.reference.vertices[1:] + self.reference.vertices[:1]
                ):
                    sub_e = create_element("triangle", self.fine_space, self.order)

                    sub_basis = sub_e.map_to_cell([v0, v1, v2])

                    if self.range_dim == 1:
                        sub_fun = sym_sum(a * b for a, b in zip(coeffs, sub_basis))
                    else:
                        sub_fun = tuple(
                            sym_sum(a * b[i] for a, b in zip(coeffs, sub_basis))
                            for i in range(self.range_dim))
                    pieces.append(((v0, v1, v2), sub_fun))
                self._basis_functions.append(PiecewiseFunction(pieces))
        return self._basis_functions
Ejemplo n.º 10
0
def test_element(elements_to_test, cells_to_test, cell_type, element_type,
                 order, kwargs, speed):
    """Run tests for each element."""
    if elements_to_test != "ALL" and element_type not in elements_to_test:
        pytest.skip()
    if cells_to_test != "ALL" and cell_type not in cells_to_test:
        pytest.skip()
    if speed == "fast":
        if order > 2:
            pytest.skip()
        if order == 2 and cell_type in [
                "tetrahedron", "hexahedron", "prism", "pyramid"
        ]:
            pytest.skip()

    element = create_element(cell_type, element_type, order, **kwargs)
    try:
        factorised_basis = element._get_basis_functions_tensor()
    except symfem.finite_element.NoTensorProduct:
        pytest.skip(
            "This element does not have a tensor product representation.")
    basis = element.get_basis_functions()

    for i, j in zip(basis, factorised_basis):
        assert symequal(i, j)
Ejemplo n.º 11
0
def test_nedelec_3d():
    space = create_element("tetrahedron", "Nedelec", 1)
    k = sympy.Symbol("k")

    tdim = 3

    for i, edge in enumerate([((0, 1, 0), (0, 0, 1)), ((1, 0, 0), (0, 0, 1)),
                              ((1, 0, 0), (0, 1, 0)), ((0, 0, 0), (0, 0, 1)),
                              ((0, 0, 0), (0, 1, 0)), ((0, 0, 0), (1, 0, 0))]):
        for j, f in enumerate(space.get_basis_functions()):
            norm = sympy.sqrt(
                sum((edge[0][i] - edge[1][i])**2 for i in range(tdim)))
            tangent = tuple(
                (edge[1][i] - edge[0][i]) / norm for i in range(tdim))

            integrand = sum(a * b for a, b in zip(f, tangent))
            for d in range(tdim):
                integrand = integrand.subs(x[d], (1 - k) * edge[0][d] +
                                           k * edge[1][d])

            integrand *= norm

            result = sympy.integrate(integrand, (k, 0, 1))
            if i == j:
                assert result == 1
            else:
                assert result == 0
Ejemplo n.º 12
0
def test_hct():
    e = symfem.create_element("triangle", "HCT", 3)
    for f in e.get_polynomial_basis():
        # edge from (1,0) to (1/3,1/3)
        f1 = f.get_piece((half, 0))
        f2 = f.get_piece((half, half))
        line = ((1 - 2 * t[0], t[0]))
        f1 = subs(f1, x[:2], line)
        f2 = subs(f2, x[:2], line)
        assert symequal(f1, f2)
        assert symequal(grad(f1, 2), grad(f2, 2))

        # edge from (0,1) to (1/3,1/3)
        f1 = f.get_piece((half, half))
        f2 = f.get_piece((0, half))
        line = ((t[0], 1 - 2 * t[0]))
        f1 = subs(f1, x[:2], line)
        f2 = subs(f2, x[:2], line)
        assert symequal(f1, f2)
        assert symequal(grad(f1, 2), grad(f2, 2))

        # edge from (0,0) to (1/3,1/3)
        f1 = f.get_piece((0, half))
        f2 = f.get_piece((half, 0))
        line = ((t[0], t[0]))
        f1 = subs(f1, x[:2], line)
        f2 = subs(f2, x[:2], line)
        assert symequal(f1, f2)
        assert symequal(grad(f1, 2), grad(f2, 2))
Ejemplo n.º 13
0
def test_guzman_neilan_tetrahedron(order):
    e = symfem.create_element("tetrahedron", "Guzman-Neilan", order)

    mid = tuple(
        sympy.Rational(sum(i), len(i)) for i in zip(*e.reference.vertices))
    for p in e._basis[-4:]:
        for piece in p.pieces:
            print(div(piece[1]).expand())
            float(div(piece[1]).expand())

        assert subs(p, x, mid) == (0, 0, 0)
Ejemplo n.º 14
0
def test_xxyyzz():
    element = symfem.create_element("triangle", "RT", 1)

    points = [(0, 1), (1, 0), (0, 0), (half, half)]
    r1 = element.tabulate_basis(points, "xyzxyz")
    r2 = element.tabulate_basis(points, "xxyyzz")
    for i, j in zip(r1, r2):
        assert i[0] == j[0]
        assert i[1] == j[3]
        assert i[2] == j[1]
        assert i[3] == j[4]
        assert i[4] == j[2]
        assert i[5] == j[5]
Ejemplo n.º 15
0
def test_MTW_space(reference):
    e = create_element(reference, "MTW", 3)
    polynomials = e.get_polynomial_basis()
    for p in polynomials:
        assert div(p).is_real
        for vs in e.reference.sub_entities(1):
            sub_ref = create_reference(e.reference.sub_entity_types[1],
                                       [e.reference.vertices[i] for i in vs])
            p_edge = subs(p, x, [
                i + t[0] * j for i, j in zip(sub_ref.origin, sub_ref.axes[0])
            ])
            poly = vdot(p_edge, sub_ref.normal()).expand().simplify()
            assert poly.is_real or sympy.Poly(poly).degree() <= 1
Ejemplo n.º 16
0
def test_legendre(cell, order):
    if cell == "pyramid":
        pytest.xfail("Legendre polynomials not implemented for pyramids yet.")

    e = create_element(cell, "Lagrange", order)
    points = make_lattice(cell)

    basis = legendre.get_legendre_basis(e._basis, e.reference)
    values = legendre.evaluate_legendre_basis(points, e._basis, e.reference)

    for b in basis:
        assert b != 0

    values2 = np.array([[to_float(subs(b, x, p)) for b in basis]
                        for p in points])

    assert np.allclose(values, values2)
Ejemplo n.º 17
0
def test_element(elements_to_test, cells_to_test, cell_type, element_type,
                 order, kwargs, speed):
    """Run tests for each element."""
    if elements_to_test != "ALL" and element_type not in elements_to_test:
        pytest.skip()
    if cells_to_test != "ALL" and cell_type not in cells_to_test:
        pytest.skip()
    if speed == "fast":
        if order > 2:
            pytest.skip()
        if order == 2 and cell_type in [
                "tetrahedron", "hexahedron", "prism", "pyramid"
        ]:
            pytest.skip()

    space = create_element(cell_type, element_type, order, **kwargs)
    space.test()
Ejemplo n.º 18
0
def test_basis_continuity_tetrahedron(order):
    N = 5
    e = symfem.create_element("tetrahedron", "Guzman-Neilan", order)
    quarter = sympy.Rational(1, 4)
    one = sympy.Integer(1)
    for pt in [(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1),
               (quarter, quarter, quarter)]:
        for f in e.get_polynomial_basis():
            value = None
            for p in f.pieces:
                if pt in p[0]:
                    if value is None:
                        value = symfem.symbolic.subs(p[1], symfem.symbolic.x,
                                                     pt)
                    assert value == symfem.symbolic.subs(
                        p[1], symfem.symbolic.x, pt)
    for pts in combinations([(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1),
                             (quarter, quarter, quarter)], 2):
        for i in range(N + 1):
            pt = tuple(a + (b - a) * i * one / N for a, b in zip(*pts))
            for f in e.get_polynomial_basis():
                value = None
                for p in f.pieces:
                    if pts[0] in p[0] and pts[1] in p[0]:
                        if value is None:
                            value = symfem.symbolic.subs(
                                p[1], symfem.symbolic.x, pt)
                        assert value == symfem.symbolic.subs(
                            p[1], symfem.symbolic.x, pt)
    for pts in combinations([(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1),
                             (quarter, quarter, quarter)], 3):
        for i in range(N + 1):
            for j in range(N + 1 - i):
                pt = tuple(a + (b - a) * i * one / N + (c - a) * j * one / N
                           for a, b, c in zip(*pts))
                for f in e.get_polynomial_basis():
                    value = None
                    for p in f.pieces:
                        if pts[0] in p[0] and pts[1] in p[0] and pts[2] in p[0]:
                            if value is None:
                                value = symfem.symbolic.subs(
                                    p[1], symfem.symbolic.x, pt)
                            assert value == symfem.symbolic.subs(
                                p[1], symfem.symbolic.x, pt)
Ejemplo n.º 19
0
def test_BDFM_space(reference, order):
    e = create_element(reference, "BDFM", order)
    polynomials = e.get_polynomial_basis()
    tdim = e.reference.tdim
    for p in polynomials:
        for vs in e.reference.sub_entities(tdim - 1):
            sub_ref = create_reference(e.reference.sub_entity_types[tdim - 1],
                                       [e.reference.vertices[i] for i in vs])
            if tdim == 2:
                p_edge = subs(p, x, [
                    i + t[0] * j
                    for i, j in zip(sub_ref.origin, sub_ref.axes[0])
                ])
            else:
                p_edge = subs(p, x, [
                    i + t[0] * j + t[1] * k for i, j, k in zip(
                        sub_ref.origin, sub_ref.axes[0], sub_ref.axes[1])
                ])
            poly = vdot(p_edge, sub_ref.normal()).expand().simplify()
            assert poly.is_real or sympy.Poly(poly).degree() <= order - 1
Ejemplo n.º 20
0
def test_nedelec_2d():
    space = create_element("triangle", "Nedelec", 1)
    k = sympy.Symbol("k")

    tdim = 2

    for i, edge in enumerate([((1, 0), (0, 1)), ((0, 0), (0, 1)),
                              ((0, 0), (1, 0))]):
        for j, f in enumerate(space.get_basis_functions()):
            norm = sympy.sqrt(
                sum((edge[0][i] - edge[1][i])**2 for i in range(tdim)))
            tangent = tuple(
                (edge[1][i] - edge[0][i]) / norm for i in range(tdim))
            line = sympy.Curve([(1 - k) * edge[0][i] + k * edge[1][i]
                                for i in range(tdim)], (k, 0, 1))

            result = sympy.line_integrate(vdot(f, tangent), line, x[:tdim])
            if i == j:
                assert result == 1
            else:
                assert result == 0
Ejemplo n.º 21
0
def test_against_basix(has_basix, elements_to_test, cells_to_test, cell, symfem_type,
                       basix_type, order, args, speed):
    if elements_to_test != "ALL" and symfem_type not in elements_to_test:
        pytest.skip()
    if cells_to_test != "ALL" and cell not in cells_to_test:
        pytest.skip()
    if speed == "fast" and order > 2:
        pytest.skip()

    if has_basix:
        import basix
    else:
        try:
            import basix
        except ImportError:
            pytest.skip("Basix must be installed to run this test.")

    points = make_lattice(cell, 2)
    parsed_args = []
    for a in args:
        if a[0] == "LagrangeVariant":
            parsed_args.append(basix.variants.string_to_lagrange_variant(a[1]))
        elif a[0] == "DPCVariant":
            parsed_args.append(basix.variants.string_to_dpc_variant(a[1]))
        elif a[0] == "bool":
            parsed_args.append(a[1])
        else:
            raise ValueError(f"Unknown arg type: {a[0]}")
    space = basix.create_element(
        basix.finite_element.string_to_family(basix_type, cell),
        basix.cell.string_to_type(cell), order, *parsed_args)
    result = space.tabulate(0, points)[0]

    element = create_element(cell, symfem_type, order)
    sym_result = element.tabulate_basis(points, "xyz,xyz", symbolic=False, use_legendre=True)

    if len(result.shape) != len(sym_result.shape):
        sym_result = sym_result.reshape(result.shape)

    assert np.allclose(result, sym_result)
Ejemplo n.º 22
0
def test_rhct():
    e = symfem.create_element("triangle", "rHCT", 3)
    for f in e.get_polynomial_basis():
        # edge from (1,0) to (1/3,1/3)
        f1 = f.get_piece((half, 0))
        f2 = f.get_piece((half, half))
        line = ((1 - 2 * t[0], t[0]))
        f1 = subs(f1, x[:2], line)
        f2 = subs(f2, x[:2], line)
        assert symequal(f1, f2)
        assert symequal(grad(f1, 2), grad(f2, 2))

        # edge from (0,1) to (1/3,1/3)
        f1 = f.get_piece((half, half))
        f2 = f.get_piece((0, half))
        line = ((t[0], 1 - 2 * t[0]))
        f1 = subs(f1, x[:2], line)
        f2 = subs(f2, x[:2], line)
        assert symequal(f1, f2)
        assert symequal(grad(f1, 2), grad(f2, 2))

        # edge from (0,0) to (1/3,1/3)
        f1 = f.get_piece((0, half))
        f2 = f.get_piece((half, 0))
        line = ((t[0], t[0]))
        f1 = subs(f1, x[:2], line)
        f2 = subs(f2, x[:2], line)
        assert symequal(f1, f2)
        assert symequal(grad(f1, 2), grad(f2, 2))

        # Check that normal derivatives are linear
        f1 = diff(f.get_piece((half, 0)), x[1]).subs(x[1], 0)
        f2 = f.get_piece((half, half))
        f2 = (diff(f2, x[0]) + diff(f2, x[1])).subs(x[1], 1 - x[0])
        f3 = diff(f.get_piece((0, half)), x[0]).subs(x[0], 0)
        assert diff(f1, x[0], x[0]) == 0
        assert diff(f2, x[0], x[0]) == 0
        assert diff(f3, x[1], x[1]) == 0
Ejemplo n.º 23
0
def test_stiffness_matrix():
    vertices = [(0, 0), (1, 0), (0, 1), (1, 1)]
    triangles = [[0, 1, 2], [1, 3, 2]]

    matrix = [[0 for i in vertices] for j in vertices]

    element = symfem.create_element("triangle", "Lagrange", 1)
    for triangle in triangles:
        vs = [vertices[i] for i in triangle]
        ref = symfem.create_reference("triangle", vertices=vs)
        basis = element.map_to_cell(vs)
        for test_i, test_f in zip(triangle, basis):
            for trial_i, trial_f in zip(triangle, basis):
                integrand = vdot(grad(test_f, 2), grad(trial_f, 2))
                matrix[test_i][trial_i] += ref.integral(integrand)

    half = sympy.Rational(1, 2)
    actual_matrix = [[1, -half, -half, 0], [-half, 1, 0, -half],
                     [-half, 0, 1, -half], [0, -half, -half, 1]]

    for row1, row2 in zip(matrix, actual_matrix):
        for i, j in zip(row1, row2):
            assert i == j
def test_Q():
    space = create_element("quadrilateral", "Q", 1)
    assert symequal(
        space.tabulate_basis([[0, 0], [1, 0], [0, 1], [1, 1]]),
        ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)),
    )
def test_rt():
    space = create_element("triangle", "Raviart-Thomas", 1)
    assert symequal(
        space.tabulate_basis([[0, 0], [1, 0], [0, 1]], "xxyyzz"),
        ((0, -1, 0, 0, 0, 1), (-1, 0, -1, 0, 0, 1), (0, -1, 0, -1, 1, 0)),
    )
def test_nedelec():
    space = create_element("triangle", "Nedelec", 1)
    assert symequal(
        space.tabulate_basis([[0, 0], [1, 0], [0, 1]], "xxyyzz"),
        ((0, 0, 1, 0, 1, 0), (0, 0, 1, 1, 0, 1), (-1, 1, 0, 0, 1, 0)),
    )