Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
def test_assembly_dx_domains(mode, meshtags_factory):
    mesh = create_unit_square(MPI.COMM_WORLD, 10, 10, ghost_mode=mode)
    V = FunctionSpace(mesh, ("Lagrange", 1))
    u, v = ufl.TrialFunction(V), ufl.TestFunction(V)

    # Prepare a marking structures
    # indices cover all cells
    # values are [1, 2, 3, 3, ...]
    cell_map = mesh.topology.index_map(mesh.topology.dim)
    num_cells = cell_map.size_local + cell_map.num_ghosts
    indices = np.arange(0, num_cells)
    values = np.full(indices.shape, 3, dtype=np.intc)
    values[0] = 1
    values[1] = 2
    marker = meshtags_factory(mesh, mesh.topology.dim, indices, values)
    dx = ufl.Measure('dx', subdomain_data=marker, domain=mesh)
    w = Function(V)
    w.x.array[:] = 0.5

    # Assemble matrix
    a = form(w * ufl.inner(u, v) * (dx(1) + dx(2) + dx(3)))
    A = assemble_matrix(a)
    A.assemble()
    a2 = form(w * ufl.inner(u, v) * dx)
    A2 = assemble_matrix(a2)
    A2.assemble()
    assert (A - A2).norm() < 1.0e-12

    bc = dirichletbc(Function(V), range(30))

    # Assemble vector
    L = form(ufl.inner(w, v) * (dx(1) + dx(2) + dx(3)))
    b = assemble_vector(L)

    apply_lifting(b, [a], [[bc]])
    b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES,
                  mode=PETSc.ScatterMode.REVERSE)
    set_bc(b, [bc])

    L2 = form(ufl.inner(w, v) * dx)
    b2 = assemble_vector(L2)
    apply_lifting(b2, [a], [[bc]])
    b2.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES,
                   mode=PETSc.ScatterMode.REVERSE)
    set_bc(b2, [bc])
    assert (b - b2).norm() < 1.0e-12

    # Assemble scalar
    L = form(w * (dx(1) + dx(2) + dx(3)))
    s = assemble_scalar(L)
    s = mesh.comm.allreduce(s, op=MPI.SUM)
    assert s == pytest.approx(0.5, 1.0e-12)
    L2 = form(w * dx)
    s2 = assemble_scalar(L2)
    s2 = mesh.comm.allreduce(s2, op=MPI.SUM)
    assert s == pytest.approx(s2, 1.0e-12)
Ejemplo n.º 5
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)
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
def test_facet_normals(cell_type):
    """Test that FacetNormal is outward facing"""
    for count in range(5):
        mesh = unit_cell(cell_type)
        tdim = mesh.topology.dim

        V = VectorFunctionSpace(mesh, ("Lagrange", 1))
        normal = FacetNormal(mesh)
        v = Function(V)

        map_f = mesh.topology.index_map(tdim - 1)
        num_facets = map_f.size_local + map_f.num_ghosts
        indices = np.arange(0, num_facets)
        values = np.arange(0, num_facets, dtype=np.intc)
        marker = MeshTags(mesh, tdim - 1, indices, values)

        # For each facet, check that the inner product of the normal and
        # the vector that has a positive normal component on only that facet
        # is positive
        for i in range(num_facets):
            if cell_type == CellType.interval:
                co = mesh.geometry.x[i]
                v.interpolate(lambda x: x[0] - co[0])
            if cell_type == CellType.triangle:
                co = mesh.geometry.x[i]
                # Vector function that is zero at `co` and points away from `co`
                # so that there is no normal component on two edges and the integral
                # over the other edge is 1
                v.interpolate(lambda x: ((x[0] - co[0]) / 2,
                                         (x[1] - co[1]) / 2))
            elif cell_type == CellType.tetrahedron:
                co = mesh.geometry.x[i]
                # Vector function that is zero at `co` and points away from `co`
                # so that there is no normal component on three faces and the integral
                # over the other edge is 1
                v.interpolate(lambda x: ((x[0] - co[0]) / 3, (x[1] - co[1]) /
                                         3, (x[2] - co[2]) / 3))
            elif cell_type == CellType.quadrilateral:
                # function that is 0 on one edge and points away from that edge
                # so that there is no normal component on three edges
                v.interpolate(lambda x: tuple(x[j] - i % 2 if j == i // 2 else
                                              0 * x[j] for j in range(2)))
            elif cell_type == CellType.hexahedron:
                # function that is 0 on one face and points away from that face
                # so that there is no normal component on five faces
                v.interpolate(lambda x: tuple(x[j] - i % 2 if j == i // 3 else
                                              0 * x[j] for j in range(3)))

            # assert that the integrals these functions dotted with the normal over a face
            # is 1 on one face and 0 on the others
            ones = 0
            for j in range(num_facets):
                a = inner(v, normal) * ds(subdomain_data=marker,
                                          subdomain_id=j)
                result = fem.assemble_scalar(a)
                if np.isclose(result, 1):
                    ones += 1
                else:
                    assert np.isclose(result, 0)
            assert ones == 1
Ejemplo n.º 8
0
def test_facet_integral(cell_type):
    """Test that the integral of a function over a facet is correct"""
    for count in range(5):
        mesh = unit_cell(cell_type)
        tdim = mesh.topology.dim

        V = FunctionSpace(mesh, ("Lagrange", 2))
        v = Function(V)

        map_f = mesh.topology.index_map(tdim - 1)
        num_facets = map_f.size_local + map_f.num_ghosts
        indices = np.arange(0, num_facets)
        values = np.arange(0, num_facets, dtype=np.intc)
        marker = MeshTags(mesh, tdim - 1, indices, values)

        # Functions that will have the same integral over each facet
        if cell_type == CellType.triangle:
            root = 3 ** 0.25  # 4th root of 3
            v.interpolate(lambda x: (x[0] - 1 / root) ** 2 + (x[1] - root / 3) ** 2)
        elif cell_type == CellType.quadrilateral:
            v.interpolate(lambda x: x[0] * (1 - x[0]) + x[1] * (1 - x[1]))
        elif cell_type == CellType.tetrahedron:
            s = 2 ** 0.5 * 3 ** (1 / 3)  # side length
            v.interpolate(lambda x: (x[0] - s / 2) ** 2 + (x[1] - s / 2 / np.sqrt(3)) ** 2
                          + (x[2] - s * np.sqrt(2 / 3) / 4) ** 2)
        elif cell_type == CellType.hexahedron:
            v.interpolate(lambda x: x[0] * (1 - x[0]) + x[1] * (1 - x[1]) + x[2] * (1 - x[2]))

        # assert that the integral of these functions over each face are equal
        out = []
        for j in range(num_facets):
            a = v * ds(subdomain_data=marker, subdomain_id=j)
            result = fem.assemble_scalar(a)
            out.append(result)
            assert np.isclose(result, out[0])
Ejemplo n.º 9
0
def test_gmsh_input_quad(order):
    pygmsh = pytest.importorskip("pygmsh")

    # Parameterize test if gmsh gets wider support
    R = 1
    res = 0.2 if order == 2 else 0.2
    algorithm = 2 if order == 2 else 5
    element = "quad{0:d}".format(int((order + 1)**2))

    geo = pygmsh.opencascade.Geometry()
    geo.add_raw_code("Mesh.ElementOrder={0:d};".format(order))
    geo.add_ball([0, 0, 0], R, char_length=res)
    geo.add_raw_code("Recombine Surface {1};")
    geo.add_raw_code("Mesh.Algorithm = {0:d};".format(algorithm))

    msh = pygmsh.generate_mesh(geo, verbose=True, dim=2)

    if order > 2:
        # Quads order > 3 have a gmsh specific ordering, and has to be permuted.
        msh_to_dolfin = np.array([0, 3, 11, 10, 1, 2, 6, 7, 4, 9, 12, 15, 5, 8, 13, 14])
        cells = np.zeros(msh.cells_dict[element].shape)
        for i in range(len(cells)):
            for j in range(len(msh_to_dolfin)):
                cells[i, j] = msh.cells_dict[element][i, msh_to_dolfin[j]]
    else:
        # XDMF does not support higher order quads
        cells = permute_cell_ordering(msh.cells_dict[element], permutation_vtk_to_dolfin(
            CellType.quadrilateral, msh.cells_dict[element].shape[1]))

    mesh = Mesh(MPI.comm_world, CellType.quadrilateral, msh.points, cells,
                [], GhostMode.none)
    surface = assemble_scalar(1 * dx(mesh))

    assert MPI.sum(mesh.mpi_comm(), surface) == pytest.approx(4 * np.pi * R * R, rel=1e-5)
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
def xtest_tetrahedron_integral(space_type, space_order):
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", "tetrahedron", 1))
    temp_points = np.array([[-1., 0., -1.], [0., 0., 0.], [1., 0., 1.],
                            [0., 1., 0.], [0., 0., 1.]])

    for repeat in range(10):
        order = [i for i, j in enumerate(temp_points)]
        shuffle(order)
        points = np.zeros(temp_points.shape)
        for i, j in enumerate(order):
            points[j] = temp_points[i]

        cells = []
        for cell in [[0, 1, 3, 4], [1, 2, 3, 4]]:
            # Randomly number the cell
            cell_order = list(range(4))
            shuffle(cell_order)
            cells.append([order[cell[i]] for i in cell_order])

        mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)
        V = FunctionSpace(mesh, (space_type, space_order))
        Vvec = VectorFunctionSpace(mesh, ("P", 1))
        dofs = [i for i in V.dofmap.cell_dofs(0) if i in V.dofmap.cell_dofs(1)]

        for d in dofs:
            v = Function(V)
            v.vector[:] = [1 if i == d else 0 for i in range(V.dim)]
            if space_type in ["RT", "BDM"]:
                # Hdiv
                def normal(x):
                    values = np.zeros((3, x.shape[1]))
                    values[0] = [1 for i in values[0]]
                    return values

                n = Function(Vvec)
                n.interpolate(normal)
                form = ufl.inner(ufl.jump(v), n) * ufl.dS
            elif space_type in ["N1curl", "N2curl"]:
                # Hcurl
                def tangent1(x):
                    values = np.zeros((3, x.shape[1]))
                    values[1] = [1 for i in values[1]]
                    return values

                def tangent2(x):
                    values = np.zeros((3, x.shape[1]))
                    values[2] = [1 for i in values[2]]
                    return values

                t1 = Function(Vvec)
                t1.interpolate(tangent1)
                t2 = Function(Vvec)
                t2.interpolate(tangent1)
                form = ufl.inner(ufl.jump(v), t1) * ufl.dS
                form += ufl.inner(ufl.jump(v), t2) * ufl.dS
            else:
                form = ufl.jump(v) * ufl.dS

            value = fem.assemble_scalar(form)
            assert np.isclose(value, 0)
Ejemplo n.º 12
0
def test_fourth_order_quad(L, H, Z):
    """Test by comparing integration of z+x*y against sympy/scipy integration
    of a quad element. Z>0 implies curved element.

      *---------*   20-21-22-23-24-41--42--43--44
      |         |   |           |              |
      |         |   15 16 17 18 19 37  38  39  40
      |         |   |           |              |
      |         |   10 11 12 13 14 33  34  35  36
      |         |   |           |              |
      |         |   5  6  7  8  9  29  30  31  32
      |         |   |           |              |
      *---------*   0--1--2--3--4--25--26--27--28

    """
    points = np.array([[0, 0, 0], [L / 4, 0, 0], [L / 2, 0, 0],               # 0 1 2
                       [3 * L / 4, 0, 0], [L, 0, 0],                          # 3 4
                       [0, H / 4, -Z / 3], [L / 4, H / 4, -Z / 3], [L / 2, H / 4, -Z / 3],   # 5 6 7
                       [3 * L / 4, H / 4, -Z / 3], [L, H / 4, -Z / 3],                  # 8 9
                       [0, H / 2, 0], [L / 4, H / 2, 0], [L / 2, H / 2, 0],   # 10 11 12
                       [3 * L / 4, H / 2, 0], [L, H / 2, 0],                  # 13 14
                       [0, (3 / 4) * H, 0], [L / 4, (3 / 4) * H, 0],          # 15 16
                       [L / 2, (3 / 4) * H, 0], [3 * L / 4, (3 / 4) * H, 0],  # 17 18
                       [L, (3 / 4) * H, 0], [0, H, Z], [L / 4, H, Z],         # 19 20 21
                       [L / 2, H, Z], [3 * L / 4, H, Z], [L, H, Z],           # 22 23 24
                       [(5 / 4) * L, 0, 0], [(6 / 4) * L, 0, 0],              # 25 26
                       [(7 / 4) * L, 0, 0], [2 * L, 0, 0],                    # 27 28
                       [(5 / 4) * L, H / 4, -Z / 3], [(6 / 4) * L, H / 4, -Z / 3],      # 29 30
                       [(7 / 4) * L, H / 4, -Z / 3], [2 * L, H / 4, -Z / 3],            # 31 32
                       [(5 / 4) * L, H / 2, 0], [(6 / 4) * L, H / 2, 0],      # 33 34
                       [(7 / 4) * L, H / 2, 0], [2 * L, H / 2, 0],            # 35 36
                       [(5 / 4) * L, 3 / 4 * H, 0],                           # 37
                       [(6 / 4) * L, 3 / 4 * H, 0],                           # 38
                       [(7 / 4) * L, 3 / 4 * H, 0], [2 * L, 3 / 4 * H, 0],    # 39 40
                       [(5 / 4) * L, H, Z], [(6 / 4) * L, H, Z],              # 41 42
                       [(7 / 4) * L, H, Z], [2 * L, H, Z]])                   # 43 44

    # VTK ordering
    cells = np.array([[0, 4, 24, 20, 1, 2, 3, 9, 14, 19, 21, 22, 23, 5, 10, 15, 6, 7, 8, 11, 12, 13, 16, 17, 18],
                      [4, 28, 44, 24, 25, 26, 27, 32, 36, 40, 41, 42, 43, 9, 14, 19,
                       29, 30, 31, 33, 34, 35, 37, 38, 39]])
    cells = cells[:, perm_vtk(CellType.quadrilateral, cells.shape[1])]
    cell = ufl.Cell("quadrilateral", geometric_dimension=points.shape[1])
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 4))
    mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)

    def e2(x):
        return x[2] + x[0] * x[1]

    V = FunctionSpace(mesh, ("CG", 4))
    u = Function(V)
    u.interpolate(e2)

    intu = assemble_scalar(u * dx(mesh))
    intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM)

    nodes = [0, 5, 10, 15, 20]
    ref = sympy_scipy(points, nodes, 2 * L, H)
    assert ref == pytest.approx(intu, rel=1e-5)
Ejemplo n.º 13
0
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
Ejemplo n.º 14
0
def xtest_quadrilateral_integral(space_type, space_order):
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", "quadrilateral", 1))
    temp_points = np.array([[-1., -1.], [0., 0.], [1., 0.], [-1., 1.],
                            [0., 1.], [2., 2.]])

    for repeat in range(10):
        order = [i for i, j in enumerate(temp_points)]
        shuffle(order)
        points = np.zeros(temp_points.shape)
        for i, j in enumerate(order):
            points[j] = temp_points[i]

        connections = {0: [1, 2], 1: [0, 3], 2: [0, 3], 3: [1, 2]}

        cells = []
        for cell in [[0, 1, 3, 4], [1, 2, 4, 5]]:
            # Randomly number the cell
            start = choice(range(4))
            cell_order = [start]
            for i in range(2):
                diff = choice([
                    i for i in connections[start] if i not in cell_order
                ]) - cell_order[0]
                cell_order += [c + diff for c in cell_order]
            cells.append([order[cell[i]] for i in cell_order])

        mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)
        V = FunctionSpace(mesh, (space_type, space_order))
        Vvec = VectorFunctionSpace(mesh, ("P", 1))
        dofs = [i for i in V.dofmap.cell_dofs(0) if i in V.dofmap.cell_dofs(1)]

        for d in dofs:
            v = Function(V)
            v.vector[:] = [1 if i == d else 0 for i in range(V.dim)]
            if space_type in ["RTCF"]:
                # Hdiv
                def normal(x):
                    values = np.zeros((2, x.shape[1]))
                    values[0] = [1 for i in values[0]]
                    return values

                n = Function(Vvec)
                n.interpolate(normal)
                form = ufl.inner(ufl.jump(v), n) * ufl.dS
            elif space_type in ["RTCE"]:
                # Hcurl
                def tangent(x):
                    values = np.zeros((2, x.shape[1]))
                    values[1] = [1 for i in values[1]]
                    return values

                t = Function(Vvec)
                t.interpolate(tangent)
                form = ufl.inner(ufl.jump(v), t) * ufl.dS
            else:
                form = ufl.jump(v) * ufl.dS

            value = fem.assemble_scalar(form)
            assert np.isclose(value, 0)
Ejemplo n.º 15
0
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)
Ejemplo n.º 16
0
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)
Ejemplo n.º 17
0
def test_additivity(mode):
    mesh = create_unit_square(MPI.COMM_WORLD, 12, 12, ghost_mode=mode)
    V = FunctionSpace(mesh, ("Lagrange", 1))

    f1 = Function(V)
    f2 = Function(V)
    f3 = Function(V)
    f1.x.array[:] = 1.0
    f2.x.array[:] = 2.0
    f3.x.array[:] = 3.0
    j1 = ufl.inner(f1, f1) * ufl.dx(mesh)
    j2 = ufl.inner(f2, f2) * ufl.ds(mesh)
    j3 = ufl.inner(ufl.avg(f3), ufl.avg(f3)) * ufl.dS(mesh)

    # Assemble each scalar form separately
    J1 = mesh.comm.allreduce(assemble_scalar(form(j1)), op=MPI.SUM)
    J2 = mesh.comm.allreduce(assemble_scalar(form(j2)), op=MPI.SUM)
    J3 = mesh.comm.allreduce(assemble_scalar(form(j3)), op=MPI.SUM)

    # Sum forms and assemble the result
    J12 = mesh.comm.allreduce(assemble_scalar(form(j1 + j2)), op=MPI.SUM)
    J13 = mesh.comm.allreduce(assemble_scalar(form(j1 + j3)), op=MPI.SUM)
    J23 = mesh.comm.allreduce(assemble_scalar(form(j2 + j3)), op=MPI.SUM)
    J123 = mesh.comm.allreduce(assemble_scalar(form(j1 + j2 + j3)), op=MPI.SUM)

    # Compare assembled values
    assert (J1 + J2) == pytest.approx(J12)
    assert (J1 + J3) == pytest.approx(J13)
    assert (J2 + J3) == pytest.approx(J23)
    assert (J1 + J2 + J3) == pytest.approx(J123)
Ejemplo n.º 18
0
def norm_L2(u):
    """
    Returns the L2 norm of the function u
    """
    comm = u.function_space.mesh.comm
    dx = ufl.Measure("dx", u.function_space.mesh)
    norm_form = form(ufl.inner(u, u) * dx)
    norm = np.sqrt(
        comm.allreduce(assemble_scalar(norm_form), op=mpi4py.MPI.SUM))
    return norm
Ejemplo n.º 19
0
def test_xdmf_input_tri(datadir):
    with XDMFFile(MPI.COMM_WORLD,
                  os.path.join(datadir, "mesh.xdmf"),
                  "r",
                  encoding=XDMFFile.Encoding.ASCII) as xdmf:
        mesh = xdmf.read_mesh(name="Grid")
    surface = assemble_scalar(1 * dx(mesh))
    assert mesh.mpi_comm().allreduce(surface,
                                     op=MPI.SUM) == pytest.approx(4 * np.pi,
                                                                  rel=1e-4)
Ejemplo n.º 20
0
def test_gmsh_input_3d(order, cell_type):
    try:
        import gmsh
    except ImportError:
        pytest.skip()
    if cell_type == CellType.hexahedron and order > 2:
        pytest.xfail("GMSH permutation for order > 2 hexahedra not implemented in DOLFINx.")

    res = 0.2

    gmsh.initialize()
    if cell_type == CellType.hexahedron:
        gmsh.option.setNumber("Mesh.RecombinationAlgorithm", 2)
        gmsh.option.setNumber("Mesh.RecombineAll", 2)
    gmsh.option.setNumber("Mesh.CharacteristicLengthMin", res)
    gmsh.option.setNumber("Mesh.CharacteristicLengthMax", res)

    circle = gmsh.model.occ.addDisk(0, 0, 0, 1, 1)

    if cell_type == CellType.hexahedron:
        gmsh.model.occ.extrude([(2, circle)], 0, 0, 1, numElements=[5], recombine=True)
    else:
        gmsh.model.occ.extrude([(2, circle)], 0, 0, 1, numElements=[5])
    gmsh.model.occ.synchronize()

    gmsh.model.mesh.generate(3)
    gmsh.model.mesh.setOrder(order)

    idx, points, _ = gmsh.model.mesh.getNodes()
    points = points.reshape(-1, 3)
    idx -= 1
    srt = np.argsort(idx)
    assert np.all(idx[srt] == np.arange(len(idx)))
    x = points[srt]

    element_types, element_tags, node_tags = gmsh.model.mesh.getElements(dim=3)
    name, dim, order, num_nodes, local_coords, num_first_order_nodes = gmsh.model.mesh.getElementProperties(
        element_types[0])

    cells = node_tags[0].reshape(-1, num_nodes) - 1
    if cell_type == CellType.tetrahedron:
        gmsh_cell_id = MPI.COMM_WORLD.bcast(gmsh.model.mesh.getElementType("tetrahedron", order), root=0)
    elif cell_type == CellType.hexahedron:
        gmsh_cell_id = MPI.COMM_WORLD.bcast(gmsh.model.mesh.getElementType("hexahedron", order), root=0)
    gmsh.finalize()

    # Permute the mesh topology from GMSH ordering to DOLFINx ordering
    domain = ufl_mesh_from_gmsh(gmsh_cell_id, 3)
    cells = cells[:, perm_gmsh(cell_type, cells.shape[1])]

    mesh = create_mesh(MPI.COMM_WORLD, cells, x, domain)

    volume = assemble_scalar(form(1 * dx(mesh)))

    assert mesh.comm.allreduce(volume, op=MPI.SUM) == pytest.approx(np.pi, rel=10 ** (-1 - order))
Ejemplo n.º 21
0
def xtest_third_order_tri():
    #  *---*---*---*   3--11--10--2
    #  | \         |   | \        |
    #  *   *   *   *   8   7  15  13
    #  |     \     |   |    \     |
    #  *  *    *   *   9  14  6   12
    #  |         \ |   |        \ |
    #  *---*---*---*   0--4---5---1
    for H in (1.0, 2.0):
        for Z in (0.0, 0.5):
            L = 1
            points = np.array([
                [0, 0, 0],
                [L, 0, 0],
                [L, H, Z],
                [0, H, Z],  # 0, 1, 2, 3
                [L / 3, 0, 0],
                [2 * L / 3, 0, 0],  # 4, 5
                [2 * L / 3, H / 3, 0],
                [L / 3, 2 * H / 3, 0],  # 6, 7
                [0, 2 * H / 3, 0],
                [0, H / 3, 0],  # 8, 9
                [2 * L / 3, H, Z],
                [L / 3, H, Z],  # 10, 11
                [L, H / 3, 0],
                [L, 2 * H / 3, 0],  # 12, 13
                [L / 3, H / 3, 0],  # 14
                [2 * L / 3, 2 * H / 3, 0]
            ])  # 15
            cells = np.array([[0, 1, 3, 4, 5, 6, 7, 8, 9, 14],
                              [1, 2, 3, 12, 13, 10, 11, 7, 6, 15]])
            cells = permute_cell_ordering(
                cells,
                permutation_vtk_to_dolfin(CellType.triangle, cells.shape[1]))
            mesh = Mesh(MPI.COMM_WORLD,
                        CellType.triangle,
                        points,
                        cells, [],
                        degree=3)

            def e2(x):
                return x[2] + x[0] * x[1]

            degree = mesh.geometry.dofmap_layout().degree()
            # Interpolate function
            V = FunctionSpace(mesh, ("CG", degree))
            u = Function(V)
            u.interpolate(e2)

            intu = assemble_scalar(u * dx(metadata={"quadrature_degree": 40}))
            intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM)

            nodes = [0, 9, 8, 3]
            ref = sympy_scipy(points, nodes, L, H)
            assert ref == pytest.approx(intu, rel=1e-6)
Ejemplo n.º 22
0
def test_integral(cell_type, space_type, space_order):
    if cell_type == "hexahedron" and space_order >= 3:
        pytest.skip("Skipping expensive test on hexahedron")

    random.seed(4)
    for repeat in range(10):
        mesh = random_evaluation_mesh(cell_type)
        tdim = mesh.topology.dim
        V = FunctionSpace(mesh, (space_type, space_order))
        Vvec = VectorFunctionSpace(mesh, ("P", 1))
        dofs = [i for i in V.dofmap.cell_dofs(0) if i in V.dofmap.cell_dofs(1)]

        for d in dofs:
            v = Function(V)
            v.vector[:] = [
                1 if i == d else 0 for i, _ in enumerate(v.vector[:])
            ]
            if space_type in ["RT", "BDM", "RTCF", "NCF", "BDMCF", "AAF"]:
                # Hdiv
                def normal(x):
                    values = np.zeros((tdim, x.shape[1]))
                    values[0] = [1 for i in values[0]]
                    return values

                n = Function(Vvec)
                n.interpolate(normal)
                _form = ufl.inner(ufl.jump(v), n) * ufl.dS
            elif space_type in [
                    "N1curl", "N2curl", "RTCE", "NCE", "BDMCE", "AAE"
            ]:
                # Hcurl
                def tangent(x):
                    values = np.zeros((tdim, x.shape[1]))
                    values[1] = [1 for i in values[1]]
                    return values

                t = Function(Vvec)
                t.interpolate(tangent)
                _form = ufl.inner(ufl.jump(v), t) * ufl.dS
                if tdim == 3:

                    def tangent2(x):
                        values = np.zeros((3, x.shape[1]))
                        values[2] = [1 for i in values[2]]
                        return values

                    t2 = Function(Vvec)
                    t2.interpolate(tangent2)
                    _form += ufl.inner(ufl.jump(v), t2) * ufl.dS
            else:
                _form = ufl.jump(v) * ufl.dS

            value = assemble_scalar(form(_form))
            assert np.isclose(value, 0)
Ejemplo n.º 23
0
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)
Ejemplo n.º 24
0
def test_interpolation_nedelec(order1, order2):
    mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2)
    V = FunctionSpace(mesh, ("N1curl", order1))
    V1 = FunctionSpace(mesh, ("N1curl", order2))
    u, v = Function(V), Function(V1)

    # The expression "lambda x: x" is contained in the N1curl function
    # space for order > 1
    u.interpolate(lambda x: x)
    v.interpolate(u)
    assert np.isclose(assemble_scalar(form(ufl.inner(u - v, u - v) * ufl.dx)),
                      0)

    # The target expression is also contained in N2curl space of any
    # order
    V2 = FunctionSpace(mesh, ("N2curl", 1))
    w = Function(V2)
    w.interpolate(u)
    assert np.isclose(assemble_scalar(form(ufl.inner(u - w, u - w) * ufl.dx)),
                      0)
Ejemplo n.º 25
0
def test_third_order_quad(L, H, Z):
    """Test by comparing integration of z+x*y against sympy/scipy integration
    of a quad element. Z>0 implies curved element.

      *---------*   3--8--9--2-22-23-17
      |         |   |        |       |
      |         |   11 14 15 7 26 27 21
      |         |   |        |       |
      |         |   10 12 13 6 24 25 20
      |         |   |        |       |
      *---------*   0--4--5--1-18-19-16

    """
    points = np.array([[0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z],        # 0  1 2 3
                       [L / 3, 0, 0], [2 * L / 3, 0, 0],                  # 4  5
                       [L, H / 3, 0], [L, 2 * H / 3, 0],                  # 6  7
                       [L / 3, H, Z], [2 * L / 3, H, Z],                  # 8  9
                       [0, H / 3, 0], [0, 2 * H / 3, 0],                  # 10 11
                       [L / 3, H / 3, 0], [2 * L / 3, H / 3, 0],          # 12 13
                       [L / 3, 2 * H / 3, 0], [2 * L / 3, 2 * H / 3, 0],  # 14 15
                       [2 * L, 0, 0], [2 * L, H, Z],                      # 16 17
                       [4 * L / 3, 0, 0], [5 * L / 3, 0, 0],              # 18 19
                       [2 * L, H / 3, 0], [2 * L, 2 * H / 3, 0],          # 20 21
                       [4 * L / 3, H, Z], [5 * L / 3, H, Z],              # 22 23
                       [4 * L / 3, H / 3, 0], [5 * L / 3, H / 3, 0],           # 24 25
                       [4 * L / 3, 2 * H / 3, 0], [5 * L / 3, 2 * H / 3, 0]])  # 26 27

    # Change to multiple cells when matthews dof-maps work for quads
    cells = np.array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
                      [1, 16, 17, 2, 18, 19, 20, 21, 22, 23, 6, 7, 24, 25, 26, 27]])

    cells = permute_cell_ordering(cells, permutation_vtk_to_dolfin(CellType.quadrilateral, cells.shape[1]))
    mesh = Mesh(MPI.comm_world, CellType.quadrilateral, points, cells,
                [], GhostMode.none)

    def e2(x):
        return x[2] + x[0] * x[1]

    # Interpolate function
    V = FunctionSpace(mesh, ("CG", 3))
    u = Function(V)
    cmap = fem.create_coordinate_map(mesh.ufl_domain())

    mesh.geometry.coord_mapping = cmap

    u.interpolate(e2)

    intu = assemble_scalar(u * dx(mesh))
    intu = MPI.sum(mesh.mpi_comm(), intu)

    nodes = [0, 3, 10, 11]
    ref = sympy_scipy(points, nodes, 2 * L, H)
    assert ref == pytest.approx(intu, rel=1e-6)
Ejemplo n.º 26
0
def test_interpolation_n2curl_to_bdm(tdim, order):
    if tdim == 2:
        mesh = create_unit_square(MPI.COMM_WORLD, 5, 5)
    else:
        mesh = create_unit_cube(MPI.COMM_WORLD, 2, 2, 2)
    V = FunctionSpace(mesh, ("N2curl", order))
    V1 = FunctionSpace(mesh, ("BDM", order))
    u, v = Function(V), Function(V1)
    u.interpolate(lambda x: x[:tdim]**order)
    v.interpolate(u)
    s = assemble_scalar(form(ufl.inner(u - v, u - v) * ufl.dx))
    assert np.isclose(s, 0)
Ejemplo n.º 27
0
def test_third_order_tri():
    #  *---*---*---*   3--11--10--2
    #  | \         |   | \        |
    #  *   *   *   *   8   7  15  13
    #  |     \     |   |    \     |
    #  *  *    *   *   9  14  6   12
    #  |         \ |   |        \ |
    #  *---*---*---*   0--4---5---1
    for H in (1.0, 2.0):
        for Z in (0.0, 0.5):
            L = 1
            points = np.array([
                [0, 0, 0],
                [L, 0, 0],
                [L, H, Z],
                [0, H, Z],  # 0, 1, 2, 3
                [L / 3, 0, 0],
                [2 * L / 3, 0, 0],  # 4, 5
                [2 * L / 3, H / 3, 0],
                [L / 3, 2 * H / 3, 0],  # 6, 7
                [0, 2 * H / 3, 0],
                [0, H / 3, 0],  # 8, 9
                [2 * L / 3, H, Z],
                [L / 3, H, Z],  # 10, 11
                [L, H / 3, 0],
                [L, 2 * H / 3, 0],  # 12, 13
                [L / 3, H / 3, 0],  # 14
                [2 * L / 3, 2 * H / 3, 0]
            ])  # 15
            cells = np.array([[0, 1, 3, 4, 5, 6, 7, 8, 9, 14],
                              [1, 2, 3, 12, 13, 10, 11, 7, 6, 15]])
            cells = cells[:, perm_vtk(CellType.triangle, cells.shape[1])]

            cell = ufl.Cell("triangle", geometric_dimension=points.shape[1])
            domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 3))
            mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)

            def e2(x):
                return x[2] + x[0] * x[1]

            # Interpolate function
            V = FunctionSpace(mesh, ("Lagrange", 3))
            u = Function(V)
            u.interpolate(e2)

            intu = assemble_scalar(u * dx(metadata={"quadrature_degree": 40}))
            intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM)

            nodes = [0, 9, 8, 3]
            ref = sympy_scipy(points, nodes, L, H)
            assert ref == pytest.approx(intu, rel=1e-6)
Ejemplo n.º 28
0
def test_integral(cell_type, space_type, space_order):
    # TODO: Fix jump integrals in FFC by passing in full info for both cells, then re-enable these tests
    pytest.xfail()

    random.seed(4)
    for repeat in range(10):
        mesh = random_evaluation_mesh(cell_type)
        tdim = mesh.topology.dim
        V = FunctionSpace(mesh, (space_type, space_order))
        Vvec = VectorFunctionSpace(mesh, ("P", 1))
        dofs = [i for i in V.dofmap.cell_dofs(0) if i in V.dofmap.cell_dofs(1)]

        for d in dofs:
            v = Function(V)
            v.vector[:] = [1 if i == d else 0 for i in range(V.dim)]
            if space_type in ["RT", "BDM", "RTCF", "NCF"]:
                # Hdiv
                def normal(x):
                    values = np.zeros((tdim, x.shape[1]))
                    values[0] = [1 for i in values[0]]
                    return values

                n = Function(Vvec)
                n.interpolate(normal)
                form = ufl.inner(ufl.jump(v), n) * ufl.dS
            elif space_type in ["N1curl", "N2curl", "RTCE", "NCE"]:
                # Hcurl
                def tangent(x):
                    values = np.zeros((tdim, x.shape[1]))
                    values[1] = [1 for i in values[1]]
                    return values

                t = Function(Vvec)
                t.interpolate(tangent)
                form = ufl.inner(ufl.jump(v), t) * ufl.dS
                if tdim == 3:

                    def tangent2(x):
                        values = np.zeros((3, x.shape[1]))
                        values[2] = [1 for i in values[2]]
                        return values

                    t2 = Function(Vvec)
                    t2.interpolate(tangent2)
                    form += ufl.inner(ufl.jump(v), t2) * ufl.dS
            else:
                form = ufl.jump(v) * ufl.dS

            value = fem.assemble_scalar(form)
            assert np.isclose(value, 0)
Ejemplo n.º 29
0
def test_manufactured_vector1(family, degree, filename, datadir):
    """Projection into H(div/curl) spaces"""

    with XDMFFile(MPI.COMM_WORLD,
                  os.path.join(datadir, filename),
                  "r",
                  encoding=XDMFFile.Encoding.ASCII) as xdmf:
        mesh = xdmf.read_mesh(name="Grid")

    V = FunctionSpace(mesh, (family, degree))
    W = VectorFunctionSpace(mesh, ("CG", degree))
    u, v = ufl.TrialFunction(V), ufl.TestFunction(V)
    a = inner(u, v) * dx

    # Source term
    x = SpatialCoordinate(mesh)
    u_ref = x[0]**degree
    L = inner(u_ref, v[0]) * dx

    b = assemble_vector(L)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)

    A = assemble_matrix(a)
    A.assemble()

    # Create LU linear solver (Note: need to use a solver that
    # re-orders to handle pivots, e.g. not the PETSc built-in LU
    # solver)
    solver = PETSc.KSP().create(MPI.COMM_WORLD)
    solver.setType("preonly")
    solver.getPC().setType('lu')
    solver.setOperators(A)

    # Solve
    uh = Function(V)
    solver.solve(b, uh.vector)
    uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                          mode=PETSc.ScatterMode.FORWARD)

    u_exact = Function(W)
    u_exact.interpolate(lambda x: np.array([
        x[0]**degree if i == 0 else 0 * x[0] for i in range(mesh.topology.dim)
    ]))

    M = inner(uh - u_exact, uh - u_exact) * dx
    M = fem.Form(M)
    error = mesh.mpi_comm().allreduce(assemble_scalar(M), op=MPI.SUM)

    assert np.absolute(error) < 1.0e-14
Ejemplo n.º 30
0
def test_third_order_quad(L, H, Z):
    """Test by comparing integration of z+x*y against sympy/scipy integration
    of a quad element. Z>0 implies curved element.

      *---------*   3--8--9--2-22-23-17
      |         |   |        |       |
      |         |   11 14 15 7 26 27 21
      |         |   |        |       |
      |         |   10 12 13 6 24 25 20
      |         |   |        |       |
      *---------*   0--4--5--1-18-19-16

    """
    points = np.array([[0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z],        # 0  1 2 3
                       [L / 3, 0, 0], [2 * L / 3, 0, 0],                  # 4  5
                       [L, H / 3, 0], [L, 2 * H / 3, 0],                  # 6  7
                       [L / 3, H, Z], [2 * L / 3, H, Z],                  # 8  9
                       [0, H / 3, 0], [0, 2 * H / 3, 0],                  # 10 11
                       [L / 3, H / 3, 0], [2 * L / 3, H / 3, 0],          # 12 13
                       [L / 3, 2 * H / 3, 0], [2 * L / 3, 2 * H / 3, 0],  # 14 15
                       [2 * L, 0, 0], [2 * L, H, Z],                      # 16 17
                       [4 * L / 3, 0, 0], [5 * L / 3, 0, 0],              # 18 19
                       [2 * L, H / 3, 0], [2 * L, 2 * H / 3, 0],          # 20 21
                       [4 * L / 3, H, Z], [5 * L / 3, H, Z],              # 22 23
                       [4 * L / 3, H / 3, 0], [5 * L / 3, H / 3, 0],           # 24 25
                       [4 * L / 3, 2 * H / 3, 0], [5 * L / 3, 2 * H / 3, 0]])  # 26 27

    # Change to multiple cells when matthews dof-maps work for quads
    cells = np.array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
                      [1, 16, 17, 2, 18, 19, 20, 21, 22, 23, 6, 7, 24, 25, 26, 27]])
    cells = cells[:, perm_vtk(CellType.quadrilateral, cells.shape[1])]
    cell = ufl.Cell("quadrilateral", geometric_dimension=points.shape[1])
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 3))
    mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)

    def e2(x):
        return x[2] + x[0] * x[1]

    # Interpolate function
    V = FunctionSpace(mesh, ("CG", 3))
    u = Function(V)
    u.interpolate(e2)

    intu = assemble_scalar(u * dx(mesh))
    intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM)

    nodes = [0, 3, 10, 11]
    ref = sympy_scipy(points, nodes, 2 * L, H)
    assert ref == pytest.approx(intu, rel=1e-6)