示例#1
0
def facet_reference_edge_vectors(L, tablename, cellname):
    celltype = getattr(basix.CellType, cellname)
    topology = basix.topology(celltype)
    geometry = basix.geometry(celltype)
    triangle_edges = basix.topology(basix.CellType.triangle)[1]
    quadrilateral_edges = basix.topology(basix.CellType.quadrilateral)[1]

    if len(topology) != 4:
        raise ValueError("Can only get facet edges for 3D cells.")

    edge_vectors = []
    for facet in topology[-2]:
        if len(facet) == 3:
            edge_vectors += [
                geometry[facet[j]] - geometry[facet[i]]
                for i, j in triangle_edges
            ]
        elif len(facet) == 4:
            edge_vectors += [
                geometry[facet[j]] - geometry[facet[i]]
                for i, j in quadrilateral_edges
            ]
        else:
            raise ValueError(
                "Only triangular and quadrilateral faces supported.")

    out = numpy.array(edge_vectors)
    return L.ArrayDecl("static const double", f"{cellname}_{tablename}",
                       out.shape, out)
示例#2
0
def run_map_test(e, J, detJ, K, reference_value_size, physical_value_size):
    tdim = len(basix.topology(e.cell_type)) - 1
    N = 5
    if tdim == 1:
        points = np.array([[i / N] for i in range(N + 1)])
    elif tdim == 2:
        points = np.array([[i / N, j / N] for i in range(N + 1)
                           for j in range(N + 1 - i)])
    elif tdim == 3:
        points = np.array([[i / N, j / N, k / N] for i in range(N + 1)
                           for j in range(N + 1 - i)
                           for k in range(N + 1 - i - j)])
    values = e.tabulate(0, points)[0]

    _J = np.array([J for p in points])
    _detJ = np.array([detJ for p in points])
    _K = np.array([K for p in points])

    assert values.shape[1] == e.dim
    assert values.shape[2] == reference_value_size

    mapped = e.push_forward(values, _J, _detJ, _K)
    assert mapped.shape[0] == values.shape[0]
    assert mapped.shape[1] == e.dim
    assert mapped.shape[2] == physical_value_size

    unmapped = e.pull_back(mapped, _J, _detJ, _K)
    assert np.allclose(values, unmapped)
示例#3
0
def test_interpolation(cell_type, n, element_type):
    element = basix.create_element(element_type, cell_type, n,
                                   basix.LagrangeVariant.gll_warped)
    assert element.interpolation_matrix.shape[0] == element.dim
    assert element.interpolation_matrix.shape[1] == element.points.shape[0]
    assert element.points.shape[1] == len(basix.topology(
        element.cell_type)) - 1
示例#4
0
文件: test_cell.py 项目: FEniCS/basix
def test_outward_normals(cell):
    cell_type = getattr(basix.CellType, cell)
    normals = basix.cell.facet_outward_normals(cell_type)
    facets = basix.topology(cell_type)[-2]
    geometry = basix.geometry(cell_type)
    midpoint = sum(geometry) / len(geometry)

    for normal, facet in zip(normals, facets):
        assert np.dot(geometry[facet[0]] - midpoint, normal) > 0
示例#5
0
def reference_edge_vectors(L, tablename, cellname):
    celltype = getattr(basix.CellType, cellname)
    topology = basix.topology(celltype)
    geometry = basix.geometry(celltype)

    edge_vectors = [geometry[j] - geometry[i] for i, j in topology[1]]

    out = numpy.array(edge_vectors[cellname])
    return L.ArrayDecl("static const double", f"{cellname}_{tablename}",
                       out.shape, out)
示例#6
0
文件: test_cell.py 项目: FEniCS/basix
def test_normals(cell):
    cell_type = getattr(basix.CellType, cell)
    normals = basix.cell.facet_normals(cell_type)
    facets = basix.topology(cell_type)[-2]
    geometry = basix.geometry(cell_type)

    for normal, facet in zip(normals, facets):
        assert np.isclose(np.linalg.norm(normal), 1)
        for v in facet[1:]:
            tangent = geometry[v] - geometry[facet[0]]
            assert np.isclose(np.dot(tangent, normal), 0)
示例#7
0
def map_facet_points(points, facet, cellname):
    geom = basix.geometry(basix_cells[cellname])
    facet_vertices = [
        geom[i] for i in basix.topology(basix_cells[cellname])[-2][facet]
    ]

    return [
        facet_vertices[0] + sum((i - facet_vertices[0]) * j
                                for i, j in zip(facet_vertices[1:], p))
        for p in points
    ]
示例#8
0
def map_facet_points(points, facet, cellname):
    """Map points from a reference facet to a physical facet."""
    geom = basix.geometry(basix.cell.string_to_type(cellname))
    facet_vertices = [
        geom[i]
        for i in basix.topology(basix.cell.string_to_type(cellname))[-2][facet]
    ]

    return [
        facet_vertices[0] + sum((i - facet_vertices[0]) * j
                                for i, j in zip(facet_vertices[1:], p))
        for p in points
    ]
示例#9
0
def facet_edge_vertices(L, tablename, cellname):
    celltype = getattr(basix.CellType, cellname)
    topology = basix.topology(celltype)
    triangle_edges = basix.topology(basix.CellType.triangle)[1]
    quadrilateral_edges = basix.topology(basix.CellType.quadrilateral)[1]

    if len(topology) != 4:
        raise ValueError("Can only get facet edges for 3D cells.")

    edge_vertices = []
    for facet in topology[-2]:
        if len(facet) == 3:
            edge_vertices += [[facet[i] for i in edge]
                              for edge in triangle_edges]
        elif len(facet) == 4:
            edge_vertices += [[facet[i] for i in edge]
                              for edge in quadrilateral_edges]
        else:
            raise ValueError(
                "Only triangular and quadrilateral faces supported.")

    out = numpy.array(edge_vertices, dtype=int)
    return L.ArrayDecl("static const unsigned int", f"{cellname}_{tablename}",
                       out.shape, out)
示例#10
0
def test_closure_dofs(cell_type, degree, element_type, element_args):
    element = basix.create_element(element_type, cell_type, degree,
                                   *element_args)

    entity_dofs = element.entity_dofs
    entity_closure_dofs = element.entity_closure_dofs

    topology = basix.topology(cell_type)
    connectivity = basix.cell.sub_entity_connectivity(cell_type)

    for dim, t in enumerate(topology):
        for e, _ in enumerate(t):
            for dim2 in range(dim + 1):
                for e2 in connectivity[dim][e][dim2]:
                    for dof in entity_dofs[dim2][e2]:
                        assert dof in entity_closure_dofs[dim][e]
示例#11
0
文件: test_cell.py 项目: FEniCS/basix
def test_sub_entity_connectivity(cell):
    cell_type = getattr(basix.CellType, cell)
    connectivity = basix.cell.sub_entity_connectivity(cell_type)
    topology = basix.topology(cell_type)

    assert len(connectivity) == len(topology)

    for dim, entities in enumerate(connectivity):
        assert len(entities) == len(topology[dim])
        for n, entity in enumerate(entities):
            for dim2, connected_entities in enumerate(entity):
                for n2 in connected_entities:
                    if dim > dim2:
                        for i in topology[dim2][n2]:
                            assert i in topology[dim][n]
                    else:
                        for i in topology[dim][n]:
                            assert i in topology[dim2][n2]
示例#12
0
def test_mesh_topology_against_basix(mesh_factory, ghost_mode):
    """Test that mesh cells have topology matching to Basix reference
    cell they were created from.
    """
    func, args = mesh_factory
    xfail_ghosted_quads_hexes(func, ghost_mode)
    mesh = func(*args)
    if not is_simplex(mesh.topology.cell_type):
        return

    # Create basix cell
    cell_name = cpp.mesh.to_string(mesh.topology.cell_type)
    basix_celltype = getattr(basix.CellType, cell_name)

    # Initialize all mesh entities and connectivities
    mesh.topology.create_connectivity_all()

    map = mesh.topology.index_map(mesh.topology.dim)
    num_cells = map.size_local + map.num_ghosts
    for i in range(num_cells):
        # Get indices of cell vertices
        vertex_global_indices = mesh.topology.connectivity(
            mesh.topology.dim, 0).links(i)

        # Loop over all dimensions of reference cell topology
        for d, d_topology in enumerate(basix.topology(basix_celltype)):

            # Get entities of dimension d on the cell
            entities = mesh.topology.connectivity(mesh.topology.dim,
                                                  d).links(i)
            if len(entities) == 0:  # Fixup for highest dimension
                entities = (i, )

            # Loop over all entities of fixed dimension d
            for entity_index, entity_topology in enumerate(d_topology):

                # Check that entity vertices map to cell vertices in correct order
                vertices = mesh.topology.connectivity(d, 0).links(
                    entities[entity_index])
                vertices_dolfin = np.sort(vertices)
                vertices2 = np.sort(
                    vertex_global_indices[np.array(entity_topology)])
                assert all(vertices2 == vertices_dolfin)
示例#13
0
def test_tensor_product_factorisation(cell_type, degree, element_type,
                                      element_args):
    element = basix.create_element(element_type, cell_type, degree,
                                   *element_args)
    tdim = len(basix.topology(cell_type)) - 1

    # These elements should have a factorisation
    if cell_type in [basix.CellType.quadrilateral,
                     basix.CellType.hexahedron] and element_type in [
                         basix.ElementFamily.P
                     ] and basix.LagrangeVariant.equispaced in element_args:
        assert element.has_tensor_product_factorisation

    if not element.has_tensor_product_factorisation:
        with pytest.raises(RuntimeError):
            element.get_tensor_product_representation()
        pytest.skip()

    factors = element.get_tensor_product_representation()

    lattice = basix.create_lattice(cell_type, 1, basix.LatticeType.equispaced,
                                   True)
    tab1 = element.tabulate(1, lattice)

    for i, point in enumerate(lattice):
        for ds in product(range(2), repeat=tdim):
            if sum(ds) > 1:
                continue
            deriv = basix.index(*ds)
            values1 = tab1[deriv, i, :, :]

            values2 = np.empty((element.dim, 1))
            for fs, perm in factors:
                evals = [
                    e.tabulate(d, [p])[d, 0, :, 0]
                    for e, p, d in zip(fs, point, ds)
                ]
                tab2 = tensor_product(*evals)
                for a, b in enumerate(perm):
                    if b != -1:
                        values2[b, 0] = tab2[a]
            assert np.allclose(values1, values2)
示例#14
0
文件: test_rt.py 项目: FEniCS/basix
def sympy_rt(celltype, n):
    x = sympy.Symbol("x")
    y = sympy.Symbol("y")
    z = sympy.Symbol("z")

    from sympy import S
    topology = basix.topology(celltype)
    geometry = S(basix.geometry(celltype).astype(int))
    dummy = [
        sympy.Symbol("DUMMY1"),
        sympy.Symbol("DUMMY2"),
        sympy.Symbol("DUMMY3")
    ]

    funcs = []
    if celltype == basix.CellType.triangle:
        tdim = 2
        for i in range(n):
            for j in range(n - i):
                for d in range(2):
                    funcs += [[x**j * y**i if k == d else 0 for k in range(2)]]
        for i in range(n):
            funcs.append([x**(n - i) * y**i, x**(n - 1 - i) * y**(i + 1)])

        mat = numpy.empty((len(funcs), len(funcs)), dtype=object)

        # edge normals
        for i, f in enumerate(funcs):
            if n == 1:
                edge_basis = [sympy.Integer(1)]
            else:
                edge_basis = sympy_lagrange(basix.CellType.interval, n - 1)
            edge_basis = [a.subs(x, dummy[0]) for a in edge_basis]
            j = 0
            for edge in topology[1]:
                edge_geom = [geometry[t, :] for t in edge]
                tangent = edge_geom[1] - edge_geom[0]
                norm = sympy.sqrt(sum(i**2 for i in tangent))
                tangent = [i / norm for i in tangent]
                normal = [-tangent[1], tangent[0]]
                param = [(1 - dummy[0]) * a + dummy[0] * b
                         for a, b in zip(edge_geom[0], edge_geom[1])]

                for g in edge_basis:
                    integrand = sum((f_i * v_i) for f_i, v_i in zip(f, normal))

                    integrand = integrand.subs(x, param[0]).subs(y, param[1])

                    integrand *= g * norm

                    mat[i, j] = integrand.integrate((dummy[0], 0, 1))
                    j += 1
        # interior dofs
        if n > 1:
            for i, f in enumerate(funcs):
                if n == 2:
                    face_basis = [sympy.Integer(1)]
                else:
                    face_basis = sympy_lagrange(basix.CellType.triangle, n - 2)

                j = n * 3
                for g in face_basis:
                    for vec in [(1, 0), (0, 1)]:
                        integrand = sum(
                            (f_i * v_i) for f_i, v_i in zip(f, vec)) * g

                        mat[i, j] = integrand.integrate(
                            (x, 0, 1 - y)).integrate((y, 0, 1))
                        j += 1

    elif celltype == basix.CellType.tetrahedron:
        tdim = 3
        for i in range(n):
            for j in range(n - i):
                for k in range(n - i - j):
                    for d in range(3):
                        funcs += [[
                            x**k * y**j * z**i if m == d else 0
                            for m in range(3)
                        ]]

        for j in range(n):
            for k in range(n - j):
                p = x**(n - 1 - j - k) * y**j * z**k
                funcs.append((x * p, y * p, z * p))

        mat = numpy.empty((len(funcs), len(funcs)), dtype=object)

        # face normals
        for i, f in enumerate(funcs):
            if n == 1:
                face_basis = [sympy.Integer(1)]
            else:
                face_basis = sympy_lagrange(basix.CellType.triangle, n - 1)
            face_basis = [
                a.subs(x, dummy[0]).subs(y, dummy[1]) for a in face_basis
            ]
            j = 0
            for face in topology[2]:
                face_geom = [geometry[t, :] for t in face]
                axes = [
                    face_geom[1] - face_geom[0], face_geom[2] - face_geom[0]
                ]
                normal = [
                    axes[0][1] * axes[1][2] - axes[0][2] * axes[1][1],
                    axes[0][2] * axes[1][0] - axes[0][0] * axes[1][2],
                    axes[0][0] * axes[1][1] - axes[0][1] * axes[1][0]
                ]
                norm = sympy.sqrt(sum(i**2 for i in normal))
                normal = [k / norm for k in normal]

                param = [
                    a + dummy[0] * b + dummy[1] * c
                    for a, b, c in zip(face_geom[0], *axes)
                ]
                for g in face_basis:
                    integrand = sum(f_i * v_i for f_i, v_i in zip(f, normal))
                    integrand = integrand.subs(x, param[0]).subs(
                        y, param[1]).subs(z, param[2])
                    integrand *= g * norm

                    mat[i, j] = integrand.integrate(
                        (dummy[0], 0, 1 - dummy[1])).integrate(
                            (dummy[1], 0, 1))
                    j += 1
            assert j == 2 * n * (n + 1)
        if n > 1:
            for i, f in enumerate(funcs):
                if n == 2:
                    interior_basis = [sympy.Integer(1)]
                else:
                    interior_basis = sympy_lagrange(basix.CellType.tetrahedron,
                                                    n - 2)
                j = 2 * n * (n + 1)
                for g in interior_basis:
                    for vec in [(1, 0, 0), (0, 1, 0), (0, 0, 1)]:
                        integrand = sum(f_i * v_i for f_i, v_i in zip(f, vec))
                        integrand *= g

                        mat[i, j] = integrand.integrate(
                            (x, 0, 1 - y - z)).integrate(
                                (y, 0, 1 - z)).integrate((z, 0, 1))
                        j += 1

    mat = sympy.Matrix(mat)
    mat = mat.inv()
    g = []
    for r in range(mat.shape[0]):
        row = []
        for dim in range(tdim):
            row.append(
                sum([v * funcs[i][dim] for i, v in enumerate(mat.row(r))]))
        g.append(row)
    return g
示例#15
0
def sympy_lagrange(celltype, n):
    x = sympy.Symbol("x")
    y = sympy.Symbol("y")
    z = sympy.Symbol("z")

    from sympy import S
    topology = basix.topology(celltype)
    geometry = S(basix.geometry(celltype).astype(int))
    pt = []
    for dim, entities in enumerate(topology):
        for ent in entities:
            entity_geom = [geometry[t, :] for t in ent]

            if (dim == 0):
                pt += [entity_geom[0]]
            elif (dim == 1):
                for i in range(n - 1):
                    pt += [
                        entity_geom[0] + sympy.Rational(i + 1, n) *
                        (entity_geom[1] - entity_geom[0])
                    ]
            elif (dim == 2):
                for i in range(n - 2):
                    for j in range(n - 2 - i):
                        pt += [
                            entity_geom[0] + sympy.Rational(i + 1, n) *
                            (entity_geom[2] - entity_geom[0]) +
                            sympy.Rational(j + 1, n) *
                            (entity_geom[1] - entity_geom[0])
                        ]
            elif (dim == 3):
                for i in range(n - 3):
                    for j in range(n - 3 - i):
                        for k in range(n - 3 - i - j):
                            pt += [
                                entity_geom[0] + sympy.Rational(i + 1, n) *
                                (entity_geom[3] - entity_geom[0]) +
                                sympy.Rational(j + 1, n) *
                                (entity_geom[2] - entity_geom[0]) +
                                sympy.Rational(k + 1, n) *
                                (entity_geom[1] - entity_geom[0])
                            ]

    funcs = []
    if celltype == basix.CellType.interval:
        for i in range(n + 1):
            funcs += [x**i]

        mat = numpy.empty((len(pt), len(funcs)), dtype=object)
        for i, f in enumerate(funcs):
            for j, p in enumerate(pt):
                mat[i, j] = f.subs([(x, p[0])])
    elif celltype == basix.CellType.triangle:
        for i in range(n + 1):
            for j in range(n + 1 - i):
                funcs += [x**j * y**i]

        mat = numpy.empty((len(pt), len(funcs)), dtype=object)
        for i, f in enumerate(funcs):
            for j, p in enumerate(pt):
                mat[i, j] = f.subs([(x, p[0]), (y, p[1])])
    elif celltype == basix.CellType.tetrahedron:
        for i in range(n + 1):
            for j in range(n + 1 - i):
                for k in range(n + 1 - i - j):
                    funcs += [x**j * y**i * z**k]

        mat = numpy.empty((len(pt), len(funcs)), dtype=object)
        for i, f in enumerate(funcs):
            for j, p in enumerate(pt):
                mat[i, j] = f.subs([(x, p[0]), (y, p[1]), (z, p[2])])

    mat = sympy.Matrix(mat)
    mat = mat.inv()
    g = []
    for r in range(mat.shape[0]):
        g += [sum([v * funcs[i] for i, v in enumerate(mat.row(r))])]

    return g
示例#16
0
        return 100 * p[0] + 30 * p[1]

def to_y(p):
    if len(p) == 1:
        return 120
    if len(p) == 2:
        return 120 - 100 * p[1]
    if len(p) == 3:
        return 120 - 100 * p[2] - 40 * p[1]


for shape in ["interval", "triangle", "tetrahedron",
              "quadrilateral", "hexahedron", "prism", "pyramid"]:
    cell_type = getattr(basix.CellType, shape)
    geometry = basix.geometry(cell_type)
    topology = basix.topology(cell_type)

    yadd = 0
    width = 100
    if shape == "interval":
        yadd = -100
    if shape == "hexahedron":
        yadd = 40
        width = 140
    if shape == "pyramid":
        width = 140
    if shape == "prism":
        yadd = 40

    svg = ""
示例#17
0
 def reference_topology(self):
     return basix.topology(self.element.cell_type)
示例#18
0
 def reference_topology(self):
     """Get the topology of the reference element."""
     return basix.topology(self.element.cell_type)
示例#19
0
def sympy_nedelec(celltype, n):
    x = sympy.Symbol("x")
    y = sympy.Symbol("y")
    z = sympy.Symbol("z")

    from sympy import S
    topology = basix.topology(celltype)
    geometry = S(basix.geometry(celltype).astype(int))
    dummy = [
        sympy.Symbol("DUMMY1"),
        sympy.Symbol("DUMMY2"),
        sympy.Symbol("DUMMY3")
    ]

    funcs = []
    if celltype == basix.CellType.triangle:
        tdim = 2
        for i in range(n + 1):
            for j in range(n + 1 - i):
                for d in range(2):
                    funcs += [[x**j * y**i if k == d else 0 for k in range(2)]]
        mat = numpy.empty((len(funcs), len(funcs)), dtype=object)

        # edge tangents
        edge_basis = sympy_lagrange(basix.CellType.interval, n)
        edge_basis = [a.subs(x, dummy[0]) for a in edge_basis]
        for i, f in enumerate(funcs):
            j = 0
            for edge in topology[1]:
                edge_geom = [geometry[t, :] for t in edge]
                tangent = edge_geom[1] - edge_geom[0]
                norm = sympy.sqrt(sum(i**2 for i in tangent))
                tangent = [i / norm for i in tangent]
                param = [(1 - dummy[0]) * a + dummy[0] * b
                         for a, b in zip(edge_geom[0], edge_geom[1])]

                for g in edge_basis:
                    integrand = sum(
                        (f_i * v_i) for f_i, v_i in zip(f, tangent))

                    integrand = integrand.subs(x, param[0]).subs(y, param[1])

                    integrand *= g * norm

                    mat[i, j] = integrand.integrate((dummy[0], 0, 1))
                    j += 1

        # interior dofs
        if n > 1:
            face_basis = sympy_rt(basix.CellType.triangle, n - 1)
            for i, f in enumerate(funcs):
                j = (n + 1) * 3
                for g in face_basis:
                    integrand = sum((f_i * v_i) for f_i, v_i in zip(f, g))

                    mat[i, j] = integrand.integrate((x, 0, 1 - y)).integrate(
                        (y, 0, 1))
                    j += 1

    elif celltype == basix.CellType.tetrahedron:
        tdim = 3
        for i in range(n + 1):
            for j in range(n + 1 - i):
                for k in range(n + 1 - i - j):
                    for d in range(3):
                        funcs += [[
                            x**k * y**j * z**i if m == d else 0
                            for m in range(3)
                        ]]

        mat = numpy.empty((len(funcs), len(funcs)), dtype=object)

        # edge tangents
        edge_basis = sympy_lagrange(basix.CellType.interval, n)
        edge_basis = [a.subs(x, dummy[0]) for a in edge_basis]
        for i, f in enumerate(funcs):
            j = 0
            for edge in topology[1]:
                edge_geom = [geometry[t, :] for t in edge]
                tangent = edge_geom[1] - edge_geom[0]
                norm = sympy.sqrt(sum(i**2 for i in tangent))
                tangent = [i / norm for i in tangent]
                param = [(1 - dummy[0]) * a + dummy[0] * b
                         for a, b in zip(edge_geom[0], edge_geom[1])]

                for g in edge_basis:
                    integrand = sum(
                        (f_i * v_i) for f_i, v_i in zip(f, tangent))
                    integrand = integrand.subs(x, param[0]).subs(
                        y, param[1]).subs(z, param[2])
                    integrand *= g * norm
                    mat[i, j] = integrand.integrate((dummy[0], 0, 1))
                    j += 1

        # face dofs
        if n > 1:
            face_basis = sympy_rt(basix.CellType.triangle, n - 1)
            face_basis = [[b.subs(x, dummy[0]).subs(y, dummy[1]) for b in a]
                          for a in face_basis]
            for i, f in enumerate(funcs):
                j = (n + 1) * 6
                for face in topology[2]:
                    face_geom = [geometry[t, :] for t in face]
                    axes = [
                        face_geom[1] - face_geom[0],
                        face_geom[2] - face_geom[0]
                    ]
                    norm = sympy.sqrt(
                        sum(i**2 for i in [
                            axes[0][1] * axes[1][2] -
                            axes[0][2] * axes[1][1], axes[0][2] * axes[1][0] -
                            axes[0][0] * axes[1][2], axes[0][0] * axes[1][1] -
                            axes[0][1] * axes[1][0]
                        ]))
                    scaled_axes = []
                    for a in axes:
                        scaled_axes.append([k / norm for k in a])
                    param = [
                        a + dummy[0] * b + dummy[1] * c
                        for a, b, c in zip(face_geom[0], *axes)
                    ]
                    this_face_basis = [[
                        a[0] * b + a[1] * c for b, c in zip(*scaled_axes)
                    ] for a in face_basis]

                    for g in this_face_basis:
                        integrand = sum(f_i * v_i for f_i, v_i in zip(f, g))
                        integrand = integrand.subs(x, param[0]).subs(
                            y, param[1]).subs(z, param[2])
                        integrand *= norm

                        mat[i, j] = integrand.integrate(
                            (dummy[0], 0, 1 - dummy[1])).integrate(
                                (dummy[1], 0, 1))
                        j += 1

        # interior dofs
        if n > 2:
            interior_basis = sympy_rt(basix.CellType.tetrahedron, n - 2)
            for i, f in enumerate(funcs):
                j = (n + 1) * 6 + 4 * (n - 1) * (n + 1)
                for g in interior_basis:
                    integrand = sum(f_i * v_i for f_i, v_i in zip(f, g))

                    mat[i, j] = integrand.integrate(
                        (x, 0, 1 - y - z)).integrate((y, 0, 1 - z)).integrate(
                            (z, 0, 1))
                    j += 1

    mat = sympy.Matrix(mat)
    mat = mat.inv()
    g = []
    for r in range(mat.shape[0]):
        row = []
        for dim in range(tdim):
            row.append(
                sum([v * funcs[i][dim] for i, v in enumerate(mat.row(r))]))
        g.append(row)

    return g
示例#20
0
def sympy_nedelec(celltype, n):
    x = sympy.Symbol("x")
    y = sympy.Symbol("y")
    z = sympy.Symbol("z")

    from sympy import S
    topology = basix.topology(celltype)
    geometry = S(basix.geometry(celltype).astype(int))
    dummy = [sympy.Symbol("DUMMY1"), sympy.Symbol("DUMMY2"), sympy.Symbol("DUMMY3")]

    funcs = []
    if celltype == basix.CellType.triangle:
        tdim = 2
        for i in range(n):
            for j in range(n - i):
                for d in range(2):
                    funcs += [[x**j * y**i if k == d else 0 for k in range(2)]]
        for i in range(n):
            funcs += [[x ** (n - 1 - i) * y ** (i + 1),
                       -x ** (n - i) * y ** i]]
        mat = numpy.empty((len(funcs), len(funcs)), dtype=object)

        # edge tangents
        if n == 1:
            edge_basis = [sympy.Integer(1)]
        else:
            edge_basis = sympy_lagrange(basix.CellType.interval, n - 1)
        edge_basis = [a.subs(x, dummy[0]) for a in edge_basis]
        for i, f in enumerate(funcs):
            j = 0
            for edge in topology[1]:
                edge_geom = [geometry[t, :] for t in edge]
                tangent = edge_geom[1] - edge_geom[0]
                norm = sympy.sqrt(sum(i ** 2 for i in tangent))
                tangent = [i / norm for i in tangent]
                param = [(1 - dummy[0]) * a + dummy[0] * b for a, b in zip(edge_geom[0], edge_geom[1])]

                for g in edge_basis:
                    integrand = sum((f_i * v_i) for f_i, v_i in zip(f, tangent))

                    integrand = integrand.subs(x, param[0]).subs(y, param[1])

                    integrand *= g * norm

                    mat[i, j] = integrand.integrate((dummy[0], 0, 1))
                    j += 1

        # interior dofs
        if n > 1:
            if n == 2:
                face_basis = [sympy.Integer(1)]
            else:
                face_basis = sympy_lagrange(basix.CellType.triangle, n - 2)
            for i, f in enumerate(funcs):
                j = n * 3
                for g in face_basis:
                    for vec in [(1, 0), (0, 1)]:
                        integrand = sum((f_i * v_i) for f_i, v_i in zip(f, vec)) * g

                        mat[i, j] = integrand.integrate((x, 0, 1 - y)).integrate((y, 0, 1))
                        j += 1

    elif celltype == basix.CellType.tetrahedron:
        tdim = 3
        for i in range(n):
            for j in range(n - i):
                for k in range(n - i - j):
                    for d in range(3):
                        funcs += [[x**k * y**j * z**i if m == d else 0 for m in range(3)]]
        if n == 1:
            funcs += [[y, -x, sympy.Integer(0)], [z, sympy.Integer(0), -x], [sympy.Integer(0), z, -y]]
        elif n == 2:
            funcs += [
                [y ** 2, -x * y, sympy.Integer(0)],
                [x * y, -x ** 2, sympy.Integer(0)],
                [z * y, -z * x, sympy.Integer(0)],
                [sympy.Integer(0), y * z, -y ** 2],
                [sympy.Integer(0), z ** 2, -z * y],
                [sympy.Integer(0), x * z, -x * y],
                [x * z, sympy.Integer(0), -x ** 2],
                [z ** 2, sympy.Integer(0), -z * x],
            ]
        elif n == 3:
            funcs += [
                [x ** 2 * y, -x ** 3, sympy.Integer(0)],
                [x ** 2 * z, sympy.Integer(0), -x ** 3],
                [sympy.Integer(0), x ** 2 * z, -x ** 2 * y],
                [x * y ** 2, -x ** 2 * y, sympy.Integer(0)],
                [2 * x * y * z, -x ** 2 * z, -x ** 2 * y],
                [sympy.Integer(0), x * y * z, -x * y ** 2],
                [x * z ** 2, sympy.Integer(0), -x ** 2 * z],
                [sympy.Integer(0), x * z ** 2, -x * y * z],
                [y ** 3, -x * y ** 2, sympy.Integer(0)],
                [9 * y ** 2 * z, -4 * x * y * z, -5 * x * y ** 2],
                [sympy.Integer(0), y ** 2 * z, -y ** 3],
                [9 * y * z ** 2, -5 * x * z ** 2, -4 * x * y * z],
                [sympy.Integer(0), y * z ** 2, -y ** 2 * z],
                [z ** 3, sympy.Integer(0), -x * z ** 2],
                [sympy.Integer(0), z ** 3, -y * z ** 2],
            ]
        else:
            raise NotImplementedError

        mat = numpy.empty((len(funcs), len(funcs)), dtype=object)

        # edge tangents
        if n == 1:
            edge_basis = [sympy.Integer(1)]
        else:
            edge_basis = sympy_lagrange(basix.CellType.interval, n - 1)
        edge_basis = [a.subs(x, dummy[0]) for a in edge_basis]
        for i, f in enumerate(funcs):
            j = 0
            for edge in topology[1]:
                edge_geom = [geometry[t, :] for t in edge]
                tangent = edge_geom[1] - edge_geom[0]
                norm = sympy.sqrt(sum(i ** 2 for i in tangent))
                tangent = [i / norm for i in tangent]
                param = [(1 - dummy[0]) * a + dummy[0] * b for a, b in zip(edge_geom[0], edge_geom[1])]

                for g in edge_basis:
                    integrand = sum((f_i * v_i) for f_i, v_i in zip(f, tangent))
                    integrand = integrand.subs(x, param[0]).subs(y, param[1]).subs(z, param[2])
                    integrand *= g * norm
                    mat[i, j] = integrand.integrate((dummy[0], 0, 1))
                    j += 1

        # face dofs
        if n > 1:

            def dot(a, b):
                return sum(i * j for i, j in zip(a, b))

            def cross(a, b):
                assert len(a) == 3 and len(b) == 3
                return [a[1] * b[2] - a[2] * b[1],
                        a[2] * b[0] - a[0] * b[2],
                        a[0] * b[1] - a[1] * b[0]]

            if n == 2:
                face_basis = [sympy.Integer(1)]
            else:
                face_basis = sympy_lagrange(basix.CellType.triangle, n - 2)
            face_basis = [a.subs(x, dummy[0]).subs(y, dummy[1]) for a in face_basis]
            for i, f in enumerate(funcs):
                j = n * 6
                for face in topology[2]:
                    face_geom = [geometry[t, :] for t in face]
                    axes = [face_geom[1] - face_geom[0], face_geom[2] - face_geom[0]]
                    norm = sympy.sqrt(sum(i**2 for i in cross(axes[0], axes[1])))

                    scaled_axes = []
                    for a in axes:
                        scaled_axes.append([k / norm for k in a])

                    param = [a + dummy[0] * b + dummy[1] * c for a, b, c in zip(face_geom[0], *axes)]
                    for g in face_basis:
                        for vec in scaled_axes:
                            integrand = dot(vec, f)
                            integrand = integrand.subs(x, param[0]).subs(y, param[1]).subs(z, param[2])
                            integrand *= g * norm

                            mat[i, j] = integrand.integrate((dummy[0], 0, 1 - dummy[1])).integrate((dummy[1], 0, 1))
                            j += 1
        # interior dofs
        if n > 2:
            if n == 3:
                interior_basis = [sympy.Integer(1)]
            else:
                interior_basis = sympy_lagrange(basix.CellType.tetrahedron, n - 3)
            for i, f in enumerate(funcs):
                j = n * 6 + 4 * n * (n - 1)
                for g in interior_basis:
                    for vec in [(1, 0, 0), (0, 1, 0), (0, 0, 1)]:
                        integrand = sum(f_i * v_i for f_i, v_i in zip(f, vec))
                        integrand *= g

                        mat[i, j] = integrand.integrate((x, 0, 1 - y - z)).integrate((y, 0, 1 - z)).integrate((z, 0, 1))
                        j += 1

    mat = sympy.Matrix(mat)
    mat = mat.inv()
    g = []
    for r in range(mat.shape[0]):
        row = []
        for dim in range(tdim):
            row.append(sum([v * funcs[i][dim] for i, v in enumerate(mat.row(r))]))
        g.append(row)
    return g