Ejemplo n.º 1
0
def test_piecewise_lagrange_tetrahedron(order):
    reference = symfem.create_reference("tetrahedron")
    mid = tuple(
        sympy.Rational(sum(i), len(i)) for i in zip(*reference.vertices))
    sub_tets = [(reference.vertices[0], reference.vertices[1],
                 reference.vertices[2], mid),
                (reference.vertices[0], reference.vertices[1],
                 reference.vertices[3], mid),
                (reference.vertices[0], reference.vertices[2],
                 reference.vertices[3], mid),
                (reference.vertices[1], reference.vertices[2],
                 reference.vertices[3], mid)]

    N = 5
    fs = make_piecewise_lagrange(sub_tets,
                                 "tetrahedron",
                                 order,
                                 zero_on_boundary=True)
    for f_n in range(reference.sub_entity_count(2)):
        face = reference.sub_entity(2, f_n)
        for i in range(N + 1):
            for j in range(N + 1 - i):
                point = face.get_point(
                    (sympy.Rational(i, N), sympy.Rational(j, N)))
                for f in fs:
                    assert subs(f, x, point) == (0, 0, 0)

    fs = make_piecewise_lagrange(sub_tets,
                                 "tetrahedron",
                                 order,
                                 zero_at_centre=True)
    for f in fs:
        assert subs(f, x, mid) == (0, 0, 0)
Ejemplo n.º 2
0
def test_piecewise_lagrange_triangle(order):
    reference = symfem.create_reference("triangle")
    mid = tuple(
        sympy.Rational(sum(i), len(i)) for i in zip(*reference.vertices))
    sub_tris = [(reference.vertices[0], reference.vertices[1], mid),
                (reference.vertices[0], reference.vertices[2], mid),
                (reference.vertices[1], reference.vertices[2], mid)]

    N = 5
    fs = make_piecewise_lagrange(sub_tris,
                                 "triangle",
                                 order,
                                 zero_on_boundary=True)
    for e_n in range(reference.sub_entity_count(1)):
        edge = reference.sub_entity(1, e_n)
        for i in range(N + 1):
            point = edge.get_point((sympy.Rational(i, N), ))
            for f in fs:
                assert subs(f, x, point) == (0, 0)

    fs = make_piecewise_lagrange(sub_tris,
                                 "triangle",
                                 order,
                                 zero_at_centre=True)
    for f in fs:
        assert subs(f, x, mid) == (0, 0)
Ejemplo n.º 3
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.º 4
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.º 5
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.º 6
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.º 7
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.º 8
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.º 9
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.º 10
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.º 11
0
# In this demo, we use the function vdot to compute the dot product of two vectors.
# The module symfem.vectors contains many functions that can be used to manipulate
# vectors.
from symfem.vectors import vdot

element = symfem.create_element("triangle", "Nedelec1", 4)
polys = element.get_polynomial_basis()

# Check that the first 20 polynomials in the polynomial basis are
# the polynomials of degree 3
p3 = polynomial_set(2, 2, 3)
assert len(p3) == 20
for i, j in zip(p3, polys[:20]):
    assert i == j

# Check that the rest of the polynomials in the polynomial basis
# satisfy p DOT x = 0
for p in polys[20:]:
    assert vdot(p, x) == 0

# Get the basis functions associated with the interior of the triangle
basis = element.get_basis_functions()
functions = [basis[d] for d in element.entity_dofs(2, 0)]

# Check that these functions have 0 tangential component on each edge
# symequal will simplify the expressions then check that they are equal
for f in functions:
    assert symequal(vdot(subs(f, x[0], 1 - x[1]), (1, -1)), 0)
    assert symequal(vdot(subs(f, x[0], 0), (0, 1)), 0)
    assert symequal(vdot(subs(f, x[1], 0), (1, 0)), 0)
Ejemplo n.º 12
0
                     (reference.vertices[0], reference.vertices[2],
                      reference.vertices[3], mid),
                     (reference.vertices[1], reference.vertices[2],
                      reference.vertices[3], mid)]
        xx, yy, zz = [i.to_sympy() for i in x]
        terms = [1, xx, yy, zz, xx**2, yy**2, zz**2, xx * yy, xx * zz, yy * zz]

    sub_basis = make_piecewise_lagrange(sub_cells, ref, br.reference.tdim,
                                        True)

    filename = os.path.join(folder, f"_guzman_neilan_{ref}.py")
    output = "import sympy\n\ncoeffs = [\n"

    for f in fs:
        output += "    [\n"
        fun = (div(f) - reference.integral(subs(div(f), x, t)) /
               reference.volume()).as_coefficients_dict()

        for term in fun:
            assert term in terms
        aim = [fun[term] if term in fun else 0
               for term in terms] * (br.reference.tdim + 1)

        mat = [[] for t in terms for p in sub_basis[0].pieces]
        for b in sub_basis:
            i = 0
            for _, p in b.pieces:
                d = div(p).expand().as_coefficients_dict()
                for term in d:
                    assert term == 0 or term in terms
                for term in terms:
Ejemplo n.º 13
0
"""

import symfem
import sympy
from symfem.symbolic import x, subs, symequal

element = symfem.create_element("triangle", "Lagrange", 5)
edge_element = symfem.create_element("interval", "Lagrange", 5)

# Define a parameter that will go from 0 to 1 on the chosen edge
a = sympy.Symbol("a")

# Get the basis functions of the Lagrange space and substitute the parameter into the
# functions on the edge
basis = element.get_basis_functions()
edge_basis = [subs(f, x[0], a) for f in edge_element.get_basis_functions()]

# Get the DOFs on edge 0 (from vertex 1 (1,0) to vertex 2 (0,1))
# (1 - a, a) is a parametrisation of this edge
dofs = element.entity_dofs(0, 1) + element.entity_dofs(
    0, 2) + element.entity_dofs(1, 0)
# Check that the basis functions on this edge are equal
for d, edge_f in zip(dofs, edge_basis):
    # symequal will simplify the expressions then check that they are equal
    assert symequal(subs(basis[d], x[:2], (1 - a, a)), edge_f)

# Get the DOFs on edge 1 (from vertex 0 (0,0) to vertex 2 (0,1), parametrised (0, a))
dofs = element.entity_dofs(0, 0) + element.entity_dofs(
    0, 2) + element.entity_dofs(1, 1)
for d, edge_f in zip(dofs, edge_basis):
    assert symequal(subs(basis[d], x[:2], (0, a)), edge_f)