예제 #1
0
def test_additivity(mode):
    mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 12, 12, ghost_mode=mode)
    V = dolfinx.FunctionSpace(mesh, ("CG", 1))

    f1 = dolfinx.Function(V)
    f2 = dolfinx.Function(V)
    f3 = dolfinx.Function(V)
    with f1.vector.localForm() as f1_local:
        f1_local.set(1.0)
    with f2.vector.localForm() as f2_local:
        f2_local.set(2.0)
    with f3.vector.localForm() as f3_local:
        f3_local.set(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.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j1), op=MPI.SUM)
    J2 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j2), op=MPI.SUM)
    J3 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j3), op=MPI.SUM)

    # Sum forms and assemble the result
    J12 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j1 + j2), op=MPI.SUM)
    J13 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j1 + j3), op=MPI.SUM)
    J23 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j2 + j3), op=MPI.SUM)
    J123 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(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)
예제 #2
0
def test_assemble_derivatives():
    """This test checks the original_coefficient_positions, which may change
    under differentiation (some coefficients and constants are
    eliminated)"""
    mesh = UnitSquareMesh(MPI.COMM_WORLD, 12, 12)
    Q = dolfinx.FunctionSpace(mesh, ("Lagrange", 1))
    u = dolfinx.Function(Q)
    v = ufl.TestFunction(Q)
    du = ufl.TrialFunction(Q)
    b = dolfinx.Function(Q)
    c1 = fem.Constant(mesh, [[1.0, 0.0], [3.0, 4.0]])
    c2 = fem.Constant(mesh, 2.0)

    with b.vector.localForm() as b_local:
        b_local.set(2.0)

    # derivative eliminates 'u' and 'c1'
    L = ufl.inner(c1, c1) * v * dx + c2 * b * inner(u, v) * dx
    a = derivative(L, u, du)

    A1 = dolfinx.fem.assemble_matrix(a)
    A1.assemble()
    a = c2 * b * inner(du, v) * dx
    A2 = dolfinx.fem.assemble_matrix(a)
    A2.assemble()
    assert (A1 - A2).norm() == pytest.approx(0.0, rel=1e-12, abs=1e-12)
예제 #3
0
def test_custom_mesh_loop_rank1():

    # Create mesh and function space
    mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, 64, 64)
    V = dolfinx.FunctionSpace(mesh, ("Lagrange", 1))

    # Unpack mesh and dofmap data
    pos = mesh.geometry.dofmap.offsets()
    x_dofs = mesh.geometry.dofmap.array()
    x = mesh.geometry.x
    dofs = V.dofmap.list.array()

    # Assemble with pure Numba function (two passes, first will include JIT overhead)
    b0 = dolfinx.Function(V)
    for i in range(2):
        with b0.vector.localForm() as b:
            b.set(0.0)
            start = time.time()
            assemble_vector(np.asarray(b), (pos, x_dofs, x), dofs)
            end = time.time()
            print("Time (numba, pass {}): {}".format(i, end - start))

    b0.vector.ghostUpdate(addv=PETSc.InsertMode.ADD,
                          mode=PETSc.ScatterMode.REVERSE)
    assert (b0.vector.sum() == pytest.approx(1.0))

    # Test against generated code and general assembler
    v = ufl.TestFunction(V)
    L = inner(1.0, v) * dx

    start = time.time()
    b1 = dolfinx.fem.assemble_vector(L)
    end = time.time()
    print("Time (C++, pass 1):", end - start)

    with b1.localForm() as b_local:
        b_local.set(0.0)
    start = time.time()
    dolfinx.fem.assemble_vector(b1, L)
    end = time.time()
    print("Time (C++, pass 2):", end - start)

    b1.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    assert ((b1 - b0.vector).norm() == pytest.approx(0.0))

    # Assemble using generated tabulate_tensor kernel and Numba assembler
    b3 = dolfinx.Function(V)
    ufc_form = dolfinx.jit.ffcx_jit(L)
    kernel = ufc_form.create_cell_integral(-1).tabulate_tensor
    for i in range(2):
        with b3.vector.localForm() as b:
            b.set(0.0)
            start = time.time()
            assemble_vector_ufc(np.asarray(b), kernel, (pos, x_dofs, x), dofs)
            end = time.time()
            print("Time (numba/cffi, pass {}): {}".format(i, end - start))

    b3.vector.ghostUpdate(addv=PETSc.InsertMode.ADD,
                          mode=PETSc.ScatterMode.REVERSE)
    assert ((b3.vector - b0.vector).norm() == pytest.approx(0.0))
예제 #4
0
def test_expression_linearise(V1, V2, squaremesh_5):

    u1, u10 = dolfinx.Function(V1), dolfinx.Function(V1)
    u2, u20 = dolfinx.Function(V2), dolfinx.Function(V2)

    dx = ufl.dx(squaremesh_5)

    # Test linearisation of expressions at u0

    assert dolfiny.expression.linearise(1 * u1, u1, u0=u10) == \
        u10 + (u1 + (-1) * u10)
    assert dolfiny.expression.linearise(2 * u1 + u2, u1, u0=u10) == \
        (u2 + 2 * u10) + (2 * u1 + (-1) * (2 * u10))
    assert dolfiny.expression.linearise(u1**2 + u2, u1, u0=u10) == \
        (u10 * (2 * u1) + (-1) * (u10 * 2 * u10)) + (u10**2 + u2)

    assert dolfiny.expression.linearise(u1**2 + u2**2, [u1, u2], u0=[u10, u20]) == \
        (u10 * (2 * u1) + u20 * (2 * u2) + (-1) * (u10 * (2 * u10) + u20 * (2 * u20))) + (u10**2 + u20**2)
    assert dolfiny.expression.linearise([u1**2, u2], u1, u0=u10) == \
        [(u10 * (2 * u1) + (-1) * (u10 * 2 * u10)) + u10**2, u2]
    assert dolfiny.expression.linearise([u1**2 + u2, u2], [u1, u2], u0=[u10, u20]) == \
        [(u10 * (2 * u1) + u2 + (-1) * (u10 * (2 * u10) + u20)) + (u10**2 + u20), (u2 + (-1) * u20) + u20]

    # Test linearisation of forms at u0

    assert dolfiny.expression.linearise(1 * u1 * dx, u1, u0=u10) == \
        u10 * dx + (u1 * dx + (-1) * u10 * dx)
    assert dolfiny.expression.linearise([u1**2 * dx, u2 * dx], u1, u0=u10) == \
        [u10**2 * dx + u10 * (2 * u1) * dx + (-1) * (u10 * 2 * u10) * dx, u2 * dx]
예제 #5
0
def test_assembly_dx_domains(mode):
    mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD,
                                             10,
                                             10,
                                             ghost_mode=mode)
    V = dolfinx.FunctionSpace(mesh, ("CG", 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 = numpy.arange(0, num_cells)
    values = numpy.full(indices.shape, 3, dtype=numpy.intc)
    values[0] = 1
    values[1] = 2
    marker = dolfinx.mesh.MeshTags(mesh, mesh.topology.dim, indices, values)
    dx = ufl.Measure('dx', subdomain_data=marker, domain=mesh)
    w = dolfinx.Function(V)
    with w.vector.localForm() as w_local:
        w_local.set(0.5)

    bc = dolfinx.fem.DirichletBC(dolfinx.Function(V), range(30))

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

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

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

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

    # Assemble scalar
    L = w * (dx(1) + dx(2) + dx(3))
    s = dolfinx.fem.assemble_scalar(L)
    s = mesh.mpi_comm().allreduce(s, op=MPI.SUM)
    assert s == pytest.approx(0.5, 1.0e-12)
    L2 = w * dx
    s2 = dolfinx.fem.assemble_scalar(L2)
    s2 = mesh.mpi_comm().allreduce(s2, op=MPI.SUM)
    assert s == pytest.approx(s2, 1.0e-12)
예제 #6
0
def test_expression_assemble(V1, vV1, squaremesh_5):

    u1, u2 = dolfinx.Function(V1), dolfinx.Function(vV1)

    dx = ufl.dx(squaremesh_5)

    u1.vector.set(3.0)
    u2.vector.set(2.0)
    u1.vector.ghostUpdate()
    u2.vector.ghostUpdate()

    # check assembled shapes

    assert numpy.shape(dolfiny.expression.assemble(1.0, dx)) == ()
    assert numpy.shape(dolfiny.expression.assemble(ufl.grad(u1), dx)) == (2,)
    assert numpy.shape(dolfiny.expression.assemble(ufl.grad(u2), dx)) == (2, 2)

    # check assembled values

    assert numpy.isclose(dolfiny.expression.assemble(1.0, dx), 1.0)
    assert numpy.isclose(dolfiny.expression.assemble(u1, dx), 3.0)
    assert numpy.isclose(dolfiny.expression.assemble(u2, dx), 2.0).all()
    assert numpy.isclose(dolfiny.expression.assemble(u1 * u2, dx), 6.0).all()

    assert numpy.isclose(dolfiny.expression.assemble(ufl.grad(u1), dx), 0.0).all()
    assert numpy.isclose(dolfiny.expression.assemble(ufl.grad(u2), dx), 0.0).all()
예제 #7
0
    def monolithic_solve():
        """Monolithic (interleaved) solver"""
        P2_el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2)
        P1_el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
        TH = P2_el * P1_el
        W = dolfinx.FunctionSpace(mesh, TH)
        (u, p) = ufl.TrialFunctions(W)
        (v, q) = ufl.TestFunctions(W)
        a00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx
        a01 = ufl.inner(p, ufl.div(v)) * dx
        a10 = ufl.inner(ufl.div(u), q) * dx
        a = a00 + a01 + a10

        p00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx
        p11 = ufl.inner(p, q) * dx
        p_form = p00 + p11

        f = dolfinx.Function(W.sub(0).collapse())
        p_zero = dolfinx.Function(W.sub(1).collapse())
        L0 = inner(f, v) * dx
        L1 = inner(p_zero, q) * dx
        L = L0 + L1

        bdofsW0_P2_0 = dolfinx.fem.locate_dofs_topological(
            (W.sub(0), P2), facetdim, bndry_facets0)
        bdofsW0_P2_1 = dolfinx.fem.locate_dofs_topological(
            (W.sub(0), P2), facetdim, bndry_facets1)

        bc0 = dolfinx.DirichletBC(u0, bdofsW0_P2_0, W.sub(0))
        bc1 = dolfinx.DirichletBC(u0, bdofsW0_P2_1, W.sub(0))

        A = dolfinx.fem.assemble_matrix(a, [bc0, bc1])
        A.assemble()
        P = dolfinx.fem.assemble_matrix(p_form, [bc0, bc1])
        P.assemble()

        b = dolfinx.fem.assemble_vector(L)
        dolfinx.fem.apply_lifting(b, [a], [[bc0, bc1]])
        b.ghostUpdate(addv=PETSc.InsertMode.ADD,
                      mode=PETSc.ScatterMode.REVERSE)
        dolfinx.fem.set_bc(b, [bc0, bc1])

        ksp = PETSc.KSP()
        ksp.create(mesh.mpi_comm())
        ksp.setOperators(A, P)
        ksp.setType("minres")
        pc = ksp.getPC()
        pc.setType('lu')

        def monitor(ksp, its, rnorm):
            # print("Num it, rnorm:", its, rnorm)
            pass

        ksp.setTolerances(rtol=1.0e-8, max_it=50)
        ksp.setMonitor(monitor)
        ksp.setFromOptions()
        x = A.createVecRight()
        ksp.solve(b, x)
        assert ksp.getConvergedReason() > 0
        return b.norm(), x.norm(), A.norm(), P.norm()
예제 #8
0
def test_overlapping_bcs():
    """Test that, when boundaries condition overlap, the last provided
    boundary condition is applied.
    """
    n = 23
    mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, n, n)
    V = dolfinx.fem.FunctionSpace(mesh, ("Lagrange", 1))
    u, v = ufl.TrialFunction(V), ufl.TestFunction(V)
    a = inner(u, v) * dx
    L = inner(1, v) * dx

    dofs_left = dolfinx.fem.locate_dofs_geometrical(
        V, lambda x: x[0] < 1.0 / (2.0 * n))
    dofs_top = dolfinx.fem.locate_dofs_geometrical(
        V, lambda x: x[1] > 1.0 - 1.0 / (2.0 * n))
    dof_corner = np.array(list(set(dofs_left).intersection(set(dofs_top))),
                          dtype=np.int64)

    # Check only one dof pair is found globally
    assert len(set(np.concatenate(MPI.COMM_WORLD.allgather(dof_corner)))) == 1

    u0, u1 = dolfinx.Function(V), dolfinx.Function(V)
    with u0.vector.localForm() as u0_loc:
        u0_loc.set(0)
    with u1.vector.localForm() as u1_loc:
        u1_loc.set(123.456)
    bcs = [
        dolfinx.DirichletBC(u0, dofs_left),
        dolfinx.DirichletBC(u1, dofs_top)
    ]

    A, b = dolfinx.fem.create_matrix(a), dolfinx.fem.create_vector(L)
    dolfinx.fem.assemble_matrix(A, a, bcs=bcs)
    A.assemble()

    # Check the diagonal (only on the rank that owns the row)
    d = A.getDiagonal()
    if len(dof_corner) > 0 and dof_corner[0] < V.dofmap.index_map.size_local:
        d.array_r[dof_corner[0]] == 1.0

    with b.localForm() as b_loc:
        b_loc.set(0)
    dolfinx.fem.assemble_vector(b, L)
    dolfinx.fem.apply_lifting(b, [a], [bcs])
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    dolfinx.fem.set_bc(b, bcs)
    b.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)

    if len(dof_corner) > 0:
        with b.localForm() as b_loc:
            print(b_loc[dof_corner[0]])
            assert b_loc[dof_corner[0]] == 123.456
예제 #9
0
def test_p1_trace(has_dolfinx):
    """Test the trace of a P1 Dolfin function."""
    if has_dolfinx:
        import dolfinx
        import dolfinx.geometry
    else:
        try:
            import dolfinx
            import dolfinx.geometry
        except ImportError:
            pytest.skip("DOLFIN-X must be installed to run this test")
    import bempp.api
    from bempp.api.external.fenicsx import fenics_to_bempp_trace_data

    fenics_mesh = dolfinx.UnitCubeMesh(MPI.COMM_WORLD, 2, 2, 2)
    fenics_space = dolfinx.FunctionSpace(fenics_mesh, ("CG", 1))

    bempp_space, trace_matrix = fenics_to_bempp_trace_data(fenics_space)

    fenics_coeffs = np.random.rand(fenics_space.dofmap.index_map.size_global)
    bempp_coeffs = trace_matrix @ fenics_coeffs

    fenics_fun = dolfinx.Function(fenics_space)
    fenics_fun.vector[:] = fenics_coeffs
    bempp_fun = bempp.api.GridFunction(bempp_space, coefficients=bempp_coeffs)

    tree = dolfinx.geometry.BoundingBoxTree(fenics_mesh, 3)

    for cell in bempp_space.grid.entity_iterator(0):
        mid = cell.geometry.centroid
        bempp_val = bempp_fun.evaluate(cell.index, np.array([[1 / 3], [1 / 3]]))

        fenics_cell = dolfinx.geometry.compute_closest_entity(tree, mid, fenics_mesh)[0]
        fenics_val = fenics_fun.eval([mid.T], [fenics_cell])
        assert np.isclose(bempp_val[0, 0], fenics_val[0])
예제 #10
0
def test_assemble_manifold():
    """Test assembly of poisson problem on a mesh with topological dimension 1
    but embedded in 2D (gdim=2).
    """
    points = numpy.array([[0.0, 0.0], [0.2, 0.0], [0.4, 0.0], [0.6, 0.0],
                          [0.8, 0.0], [1.0, 0.0]],
                         dtype=numpy.float64)
    cells = numpy.array([[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]],
                        dtype=numpy.int32)
    cell = ufl.Cell("interval", geometric_dimension=points.shape[1])
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 1))
    mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)
    assert mesh.geometry.dim == 2
    assert mesh.topology.dim == 1

    U = dolfinx.FunctionSpace(mesh, ("P", 1))

    u, v = ufl.TrialFunction(U), ufl.TestFunction(U)
    w = dolfinx.Function(U)

    a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx(mesh)
    L = ufl.inner(1.0, v) * ufl.dx(mesh)

    bcdofs = dolfinx.fem.locate_dofs_geometrical(
        U, lambda x: numpy.isclose(x[0], 0.0))
    bcs = [dolfinx.DirichletBC(w, bcdofs)]
    A = dolfinx.fem.assemble_matrix(a, bcs)
    A.assemble()

    b = dolfinx.fem.assemble_vector(L)
    dolfinx.fem.apply_lifting(b, [a], [bcs])
    dolfinx.fem.set_bc(b, bcs)

    assert numpy.isclose(b.norm(), 0.41231)
    assert numpy.isclose(A.norm(), 25.0199)
예제 #11
0
    def interpolate_on_mesh(self, mesh, q, u):

        # Extract mesh geometry nodal coordinates
        dm = mesh.geometry.dofmap
        oq = [0] + [*range(2, q + 1)
                    ] + [1]  # reorder lineX nodes: all ducks in a row...
        x0_idx = [[dm.links(i).tolist()[k] for k in oq]
                  for i in range(dm.num_nodes)]
        x0_idx = [item for sublist in x0_idx for item in sublist]
        x0 = mesh.geometry.x[x0_idx]

        # Interpolate solution at mesh geometry nodes
        import dolfinx
        import dolfiny.interpolation
        Q = dolfinx.FunctionSpace(mesh, ("P", q))
        uf = dolfinx.Function(Q)

        if isinstance(u, list):
            ui = []
            for u_ in u:
                dolfiny.interpolation.interpolate(u_, uf)
                ui.append(uf.vector[x0_idx])
        else:
            dolfiny.interpolation.interpolate(u, uf)
            ui = uf.vector[x0_idx]

        return x0, ui
예제 #12
0
def test_assembly_dx_domains(mesh):
    V = dolfinx.FunctionSpace(mesh, ("CG", 1))
    u, v = ufl.TrialFunction(V), ufl.TestFunction(V)

    # Prepare a marking structures
    # indices cover all cells
    # values are [1, 2, 3, 3, ...]
    imap = mesh.topology.index_map(mesh.topology.dim)
    num_cells = imap.size_local + imap.num_ghosts
    indices = numpy.arange(0, num_cells)
    values = numpy.full(indices.shape, 3, dtype=numpy.intc)
    values[0] = 1
    values[1] = 2
    marker = dolfinx.mesh.MeshTags(mesh, mesh.topology.dim, indices, values)
    dx = ufl.Measure('dx', subdomain_data=marker, domain=mesh)
    w = dolfinx.Function(V)
    with w.vector.localForm() as w_local:
        w_local.set(0.5)

    # Assemble matrix

    a = w * ufl.inner(u, v) * (dx(1) + dx(2) + dx(3))

    A = dolfinx.fem.assemble_matrix(a)
    A.assemble()
    norm1 = A.norm()

    a2 = w * ufl.inner(u, v) * dx

    A2 = dolfinx.fem.assemble_matrix(a2)
    A2.assemble()
    norm2 = A2.norm()

    assert norm1 == pytest.approx(norm2, 1.0e-12)

    # Assemble vector

    L = ufl.inner(w, v) * (dx(1) + dx(2) + dx(3))
    b = dolfinx.fem.assemble_vector(L)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)

    L2 = ufl.inner(w, v) * dx
    b2 = dolfinx.fem.assemble_vector(L2)
    b2.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)

    assert b.norm() == pytest.approx(b2.norm(), 1.0e-12)

    # Assemble scalar

    L = w * (dx(1) + dx(2) + dx(3))
    s = dolfinx.fem.assemble_scalar(L)
    s = mesh.mpi_comm().allreduce(s, op=MPI.SUM)

    L2 = w * dx
    s2 = dolfinx.fem.assemble_scalar(L2)
    s2 = mesh.mpi_comm().allreduce(s2, op=MPI.SUM)
    assert (s == pytest.approx(s2, 1.0e-12)
            and 0.5 == pytest.approx(s, 1.0e-12))
예제 #13
0
def test_assembly_ds_domains(mesh):
    V = dolfinx.FunctionSpace(mesh, ("CG", 1))
    u, v = ufl.TrialFunction(V), ufl.TestFunction(V)

    marker = dolfinx.MeshFunction("size_t", mesh, mesh.topology.dim - 1, 0)

    def bottom(x):
        return numpy.isclose(x[1], 0.0)

    def top(x):
        return numpy.isclose(x[1], 1.0)

    def left(x):
        return numpy.isclose(x[0], 0.0)

    def right(x):
        return numpy.isclose(x[0], 1.0)

    marker.mark(bottom, 111)
    marker.mark(top, 222)
    marker.mark(left, 333)
    marker.mark(right, 444)

    ds = ufl.Measure('ds', subdomain_data=marker, domain=mesh)

    w = dolfinx.Function(V)
    with w.vector.localForm() as w_local:
        w_local.set(0.5)

    # Assemble matrix
    a = w * ufl.inner(u, v) * (ds(111) + ds(222) + ds(333) + ds(444))
    A = dolfinx.fem.assemble_matrix(a)
    A.assemble()
    norm1 = A.norm()
    a2 = w * ufl.inner(u, v) * ds
    A2 = dolfinx.fem.assemble_matrix(a2)
    A2.assemble()
    norm2 = A2.norm()
    assert norm1 == pytest.approx(norm2, 1.0e-12)

    # Assemble vector
    L = ufl.inner(w, v) * (ds(111) + ds(222) + ds(333) + ds(444))
    b = dolfinx.fem.assemble_vector(L)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    L2 = ufl.inner(w, v) * ds
    b2 = dolfinx.fem.assemble_vector(L2)
    b2.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    assert b.norm() == pytest.approx(b2.norm(), 1.0e-12)

    # Assemble scalar
    L = w * (ds(111) + ds(222) + ds(333) + ds(444))
    s = dolfinx.fem.assemble_scalar(L)
    s = dolfinx.MPI.sum(mesh.mpi_comm(), s)
    L2 = w * ds
    s2 = dolfinx.fem.assemble_scalar(L2)
    s2 = dolfinx.MPI.sum(mesh.mpi_comm(), s2)
    assert (s == pytest.approx(s2, 1.0e-12)
            and 2.0 == pytest.approx(s, 1.0e-12))
예제 #14
0
def test_block(V1, V2, squaremesh_5, nest):
    mesh = squaremesh_5

    u0 = dolfinx.Function(V1, name="u0")
    u1 = dolfinx.Function(V2, name="u1")

    v0 = ufl.TestFunction(V1)
    v1 = ufl.TestFunction(V2)

    Phi = (ufl.sin(u0) - 0.5)**2 * ufl.dx(mesh) + (4.0 * u0 -
                                                   u1)**2 * ufl.dx(mesh)

    F0 = ufl.derivative(Phi, u0, v0)
    F1 = ufl.derivative(Phi, u1, v1)

    F = [F0, F1]
    u = [u0, u1]

    opts = PETSc.Options("block")

    opts.setValue('snes_type', 'newtontr')
    opts.setValue('snes_rtol', 1.0e-08)
    opts.setValue('snes_max_it', 12)

    if nest:
        opts.setValue('ksp_type', 'cg')
        opts.setValue('pc_type', 'fieldsplit')
        opts.setValue('fieldsplit_pc_type', 'lu')
        opts.setValue('ksp_rtol', 1.0e-10)
    else:
        opts.setValue('ksp_type', 'preonly')
        opts.setValue('pc_type', 'lu')
        opts.setValue('pc_factor_mat_solver_type', 'mumps')

    problem = dolfiny.snesblockproblem.SNESBlockProblem(F,
                                                        u,
                                                        nest=nest,
                                                        prefix="block")
    sol = problem.solve()

    assert problem.snes.getConvergedReason() > 0
    assert np.isclose((sol[0].vector - np.arcsin(0.5)).norm(), 0.0)
    assert np.isclose((sol[1].vector - 4.0 * np.arcsin(0.5)).norm(), 0.0)
예제 #15
0
def test_mixed_element_interpolation():
    def f(x):
        return np.ones(2, x.shape[1])

    mesh = UnitCubeMesh(MPI.COMM_WORLD, 3, 3, 3)
    el = ufl.FiniteElement("CG", mesh.ufl_cell(), 1)
    V = dolfinx.FunctionSpace(mesh, ufl.MixedElement([el, el]))
    u = dolfinx.Function(V)
    with pytest.raises(RuntimeError):
        u.interpolate(f)
예제 #16
0
def test_dof_coords_2d(degree):
    mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 10, 10)
    V = dolfinx.FunctionSpace(mesh, ("CG", degree))
    u = dolfinx.Function(V)

    u.interpolate(lambda x: x[0])
    u.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                         mode=PETSc.ScatterMode.FORWARD)
    x = V.tabulate_dof_coordinates()
    val = u.vector.array
    for i in range(len(val)):
        assert np.isclose(x[i, 0], val[i], rtol=1e-3)
예제 #17
0
def linearise(e, u, u0=None):
    """Generate the first order Taylor series expansion of UFL expressions (or list of expressions)
       for the given function(s) u at u0.

       Example (linearise around zero): linF = dolfiny.expression.linearise(F, u)
       Example (linearise around given state): linF = dolfiny.expression.linearise(F, u, u0)

    Parameters
    ----------
    e: UFL Expr/Form or list of UFL expressions/forms
    u: UFL Function or list of UFL functions
    u0: UFL Function or list of UFL functions, defaults to zero

    Returns
    -------
    1st order Taylor series expansion of expression/form (or list of expressions/forms).

    """

    if u0 is None:
        if isinstance(u, list):
            u0 = []
            for v in u:
                u0.append(dolfinx.Function(v.function_space, name=v.name + '_0'))
        else:
            u0 = dolfinx.Function(u.function_space, name=u.name + '_0')

    e0 = evaluate(e, u, u0)
    deu = derivative(e, u, u, u0)
    deu0 = derivative(e, u, u0, u0)

    if isinstance(e, list):
        de = []
        for e0_, deu_, deu0_ in zip(e0, deu, deu0):
            de.append(e0_ + (deu_ - deu0_))
    else:
        de = e0 + (deu - deu0)

    return de
예제 #18
0
def test_expression_derivative(V1, V2, squaremesh_5):

    u1, du1, v1 = dolfinx.Function(V1), ufl.TrialFunction(V1), ufl.TestFunction(V1)
    u2, du2, v2 = dolfinx.Function(V2), ufl.TrialFunction(V2), ufl.TestFunction(V2)

    dx = ufl.dx(squaremesh_5)

    # Test derivative of expressions

    assert dolfiny.expression.derivative(1 * u1, u1, du1) == 1 * du1
    assert dolfiny.expression.derivative(2 * u1 + u2, u1, du1) == 2 * du1
    assert dolfiny.expression.derivative(u1**2 + u2, u1, du1) == du1 * 2 * u1

    assert dolfiny.expression.derivative(u1 + u2, [u1, u2], [v1, v2]) == v1 + v2
    assert dolfiny.expression.derivative([u1, u2], u1, v1) == [v1, 0]
    assert dolfiny.expression.derivative([u1, u2], [u1, u2], [v1, v2]) == [v1, v2]

    # Test derivative of forms

    assert dolfiny.expression.derivative(1 * u1 * dx, u1, du1) == 1 * du1 * dx
    assert dolfiny.expression.derivative(2 * u1 * dx + u2 * dx, u1, du1) == 2 * du1 * dx
    assert dolfiny.expression.derivative(u1**2 * dx + u2 * dx, u1, du2) == du2 * 2 * u1 * dx

    assert dolfiny.expression.derivative(u1 * dx + u2 * dx, [u1, u2], [v1, v2]) == v1 * dx + v2 * dx
    assert dolfiny.expression.derivative([u1 * dx, u2 * dx], u1, v1) == [v1 * dx, ufl.Form([])]
    assert dolfiny.expression.derivative([u1 * dx, u2 * dx], [u1, u2], [v1, v2]) == [v1 * dx, v2 * dx]

    # Test derivative of expressions at u0

    u10, u20 = dolfinx.Function(V1), dolfinx.Function(V2)

    assert dolfiny.expression.derivative(1 * u1, u1, du1, u0=u10) == 1 * du1
    assert dolfiny.expression.derivative(2 * u1 + u2, u1, du1, u0=u10) == 2 * du1
    assert dolfiny.expression.derivative(u1**2 + u2, u1, du1, u0=u10) == du1 * 2 * u10

    assert dolfiny.expression.derivative(u1**2 + u2**2, [u1, u2], [v1, v2], [u10, u20]) == v1 * 2 * u10 + v2 * 2 * u20
    assert dolfiny.expression.derivative([u1**2, u2], u1, v1, u0=u10) == [v1 * 2 * u10, 0]
    assert dolfiny.expression.derivative([u1**2 + u2, u2], [u1, u2], [v1, v2], [u10, u20]) == [v1 * 2 * u10 + v2, v2]
def monolithic_assembly(clock, reps, mesh, use_cpp_forms):
    P2_el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2)
    P1_el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    TH = P2_el * P1_el
    W = dolfinx.FunctionSpace(mesh, TH)
    num_dofs = W.dim

    U = dolfinx.Function(W)
    u, p = ufl.split(U)
    v, q = ufl.TestFunctions(W)

    g = ufl.as_vector([0.0, 0.0, -1.0])
    F = (
        ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx
        + ufl.inner(p, ufl.div(v)) * ufl.dx
        + ufl.inner(ufl.div(u), q) * ufl.dx
        - ufl.inner(g, v) * ufl.dx
    )
    J = ufl.derivative(F, U, ufl.TrialFunction(W))
    bcs = []

    # Get jitted forms for better performance
    if use_cpp_forms:
        F = dolfinx.fem.assemble._create_cpp_form(F)
        J = dolfinx.fem.assemble._create_cpp_form(J)

    b = dolfinx.fem.create_vector(F)
    A = dolfinx.fem.create_matrix(J)
    for i in range(reps):
        A.zeroEntries()
        with b.localForm() as b_local:
            b_local.set(0.0)

        with dolfinx.common.Timer("ZZZ Mat Monolithic") as tmr:
            dolfinx.fem.assemble_matrix(A, J, bcs)
            A.assemble()
            clock["mat"] += tmr.elapsed()[0]

        with dolfinx.common.Timer("ZZZ Vec Monolithic") as tmr:
            dolfinx.fem.assemble_vector(b, F)
            dolfinx.fem.apply_lifting(b, [J], bcs=[bcs], x0=[U.vector], scale=-1.0)
            b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
            dolfinx.fem.set_bc(b, bcs, x0=U.vector, scale=-1.0)
            b.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)
            clock["vec"] += tmr.elapsed()[0]

    return num_dofs, A, b
예제 #20
0
def test_basic_assembly(mode):
    mesh = UnitSquareMesh(MPI.COMM_WORLD, 12, 12, ghost_mode=mode)
    V = dolfinx.FunctionSpace(mesh, ("Lagrange", 1))
    u, v = ufl.TrialFunction(V), ufl.TestFunction(V)

    f = dolfinx.Function(V)
    with f.vector.localForm() as f_local:
        f_local.set(10.0)
    a = inner(f * u, v) * dx + inner(u, v) * ds
    L = inner(f, v) * dx + inner(2.0, v) * ds

    # Initial assembly
    A = dolfinx.fem.assemble_matrix(a)
    A.assemble()
    assert isinstance(A, PETSc.Mat)
    b = dolfinx.fem.assemble_vector(L)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    assert isinstance(b, PETSc.Vec)

    # Second assembly
    normA = A.norm()
    A.zeroEntries()
    A = dolfinx.fem.assemble_matrix(A, a)
    A.assemble()
    assert isinstance(A, PETSc.Mat)
    assert normA == pytest.approx(A.norm())
    normb = b.norm()
    with b.localForm() as b_local:
        b_local.set(0.0)
    b = dolfinx.fem.assemble_vector(b, L)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    assert isinstance(b, PETSc.Vec)
    assert normb == pytest.approx(b.norm())

    # Vector re-assembly - no zeroing (but need to zero ghost entries)
    with b.localForm() as b_local:
        b_local.array[b.local_size:] = 0.0
    dolfinx.fem.assemble_vector(b, L)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    assert 2.0 * normb == pytest.approx(b.norm())

    # Matrix re-assembly (no zeroing)
    dolfinx.fem.assemble_matrix(A, a)
    A.assemble()
    assert 2.0 * normA == pytest.approx(A.norm())
예제 #21
0
def test_assemble_manifold():
    """Test assembly of poisson problem on a mesh with topological dimension 1
    but embedded in 2D (gdim=2).
    """
    points = numpy.array([[0.0, 0.0], [0.2, 0.0], [0.4, 0.0], [0.6, 0.0],
                          [0.8, 0.0], [1.0, 0.0]],
                         dtype=numpy.float64)
    cells = numpy.array([[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]],
                        dtype=numpy.int32)

    mesh = dolfinx.Mesh(dolfinx.MPI.comm_world,
                        dolfinx.cpp.mesh.CellType.interval, points, cells, [],
                        dolfinx.cpp.mesh.GhostMode.none)

    mesh.geometry.coord_mapping = dolfinx.fem.create_coordinate_map(mesh)

    assert mesh.geometry.dim == 2
    assert mesh.topology.dim == 1

    U = dolfinx.FunctionSpace(mesh, ("P", 1))

    u, v = ufl.TrialFunction(U), ufl.TestFunction(U)
    w = dolfinx.Function(U)

    a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx(mesh)
    L = ufl.inner(1.0, v) * ufl.dx(mesh)

    bcdofs = dolfinx.fem.locate_dofs_geometrical(
        U, lambda x: numpy.isclose(x[0], 0.0))
    bcs = [dolfinx.DirichletBC(w, bcdofs)]
    A = dolfinx.fem.assemble_matrix(a, bcs)
    A.assemble()

    b = dolfinx.fem.assemble_vector(L)
    dolfinx.fem.apply_lifting(b, [a], [bcs])
    dolfinx.fem.set_bc(b, bcs)

    assert numpy.isclose(b.norm(), 0.41231)
    assert numpy.isclose(A.norm(), 25.0199)
예제 #22
0
def test_monolithic(V1, V2, squaremesh_5):
    mesh = squaremesh_5

    Wel = ufl.MixedElement([V1.ufl_element(), V2.ufl_element()])
    W = dolfinx.FunctionSpace(mesh, Wel)

    u = dolfinx.Function(W)
    u0, u1 = ufl.split(u)

    v = ufl.TestFunction(W)
    v0, v1 = ufl.split(v)

    Phi = (ufl.sin(u0) - 0.5)**2 * ufl.dx(mesh) + (4.0 * u0 -
                                                   u1)**2 * ufl.dx(mesh)

    F = ufl.derivative(Phi, u, v)

    opts = PETSc.Options("monolithic")

    opts.setValue('snes_type', 'newtonls')
    opts.setValue('snes_linesearch_type', 'basic')

    opts.setValue('snes_rtol', 1.0e-10)
    opts.setValue('snes_max_it', 20)

    opts.setValue('ksp_type', 'preonly')
    opts.setValue('pc_type', 'lu')
    opts.setValue('pc_factor_mat_solver_type', 'mumps')

    problem = dolfiny.snesblockproblem.SNESBlockProblem([F], [u],
                                                        prefix="monolithic")
    sol, = problem.solve()

    u0, u1 = sol.split()
    u0 = u0.collapse()
    u1 = u1.collapse()

    assert np.isclose((u0.vector - np.arcsin(0.5)).norm(), 0.0)
    assert np.isclose((u1.vector - 4.0 * np.arcsin(0.5)).norm(), 0.0)
    return numpy.isclose(x[0], 48.0)


def left(x):
    """Marks left part of boundary, where cantilever is attached to wall"""
    return numpy.isclose(x[0], 0.0)


# Locate all facets at the free end and assign them value 1
free_end_facets = locate_entities_boundary(mesh, 1, free_end)
mt = dolfinx.mesh.MeshTags(mesh, 1, free_end_facets, 1)

ds = ufl.Measure("ds", subdomain_data=mt)

# Homogeneous boundary condition in displacement
u_bc = dolfinx.Function(U)
with u_bc.vector.localForm() as loc:
    loc.set(0.0)

# Displacement BC is applied to the left side
left_facets = locate_entities_boundary(mesh, 1, left)
bdofs = locate_dofs_topological(U, 1, left_facets)
bc = dolfinx.fem.DirichletBC(u_bc, bdofs)

# Elastic stiffness tensor and Poisson ratio
E, nu = 1.0, 1.0 / 3.0


def sigma_u(u):
    """Consitutive relation for stress-strain. Assuming plane-stress in XY"""
    eps = 0.5 * (ufl.grad(u) + ufl.grad(u).T)
예제 #24
0
# Plotting a 3D dolfinx.Function with pyvista
# ===========================================


# Interpolate a simple scalar function in 3D
def int_u(x):
    return x[0] + 3 * x[1] + 5 * x[2]


mesh = dolfinx.UnitCubeMesh(MPI.COMM_WORLD,
                            4,
                            3,
                            5,
                            cell_type=dolfinx.cpp.mesh.CellType.tetrahedron)
V = dolfinx.FunctionSpace(mesh, ("CG", 1))
u = dolfinx.Function(V)
u.interpolate(int_u)

# Extract mesh data from dolfin-X (only plot cells owned by the
# processor) and create a pyvista UnstructuredGrid
num_cells = mesh.topology.index_map(mesh.topology.dim).size_local
cell_entities = np.arange(num_cells, dtype=np.int32)
pyvista_cells, cell_types = dolfinx.plot.create_vtk_topology(
    mesh, mesh.topology.dim, cell_entities)
grid = pyvista.UnstructuredGrid(pyvista_cells, cell_types, mesh.geometry.x)

# Compute the function values at the vertices, this is equivalent to a
# P1 Lagrange interpolation, and can be directly attached to the Pyvista
# mesh. Discard complex value if running dolfin-X with complex PETSc as
# backend
vertex_values = u.compute_point_values()
예제 #25
0
def test_assembly_solve_taylor_hood(mesh):
    """Assemble Stokes problem with Taylor-Hood elements and solve."""
    gdim = mesh.geometry.dim
    P2 = dolfinx.function.VectorFunctionSpace(mesh, ("Lagrange", 2))
    P1 = dolfinx.function.FunctionSpace(mesh, ("Lagrange", 1))

    def boundary0(x):
        """Define boundary x = 0"""
        return x[0] < 10 * numpy.finfo(float).eps

    def boundary1(x):
        """Define boundary x = 1"""
        return x[0] > (1.0 - 10 * numpy.finfo(float).eps)

    def initial_guess_u(x):
        u_init = numpy.row_stack((numpy.sin(x[0]) * numpy.sin(x[1]),
                                  numpy.cos(x[0]) * numpy.cos(x[1])))
        if gdim == 3:
            u_init = numpy.row_stack((u_init, numpy.cos(x[2])))
        return u_init

    def initial_guess_p(x):
        return -x[0]**2 - x[1]**3

    u_bc_0 = dolfinx.Function(P2)
    u_bc_0.interpolate(
        lambda x: numpy.row_stack(tuple(x[j] + float(j) for j in range(gdim))))

    u_bc_1 = dolfinx.Function(P2)
    u_bc_1.interpolate(
        lambda x: numpy.row_stack(tuple(numpy.sin(x[j]) for j in range(gdim))))

    facetdim = mesh.topology.dim - 1
    mf = dolfinx.MeshFunction("size_t", mesh, facetdim, 0)
    mf.mark(boundary0, 1)
    mf.mark(boundary1, 2)
    bndry_facets0 = numpy.where(mf.values == 1)[0]
    bndry_facets1 = numpy.where(mf.values == 2)[0]

    bdofs0 = dolfinx.fem.locate_dofs_topological(P2, facetdim, bndry_facets0)
    bdofs1 = dolfinx.fem.locate_dofs_topological(P2, facetdim, bndry_facets1)

    bcs = [
        dolfinx.DirichletBC(u_bc_0, bdofs0),
        dolfinx.DirichletBC(u_bc_1, bdofs1)
    ]

    u, p = dolfinx.Function(P2), dolfinx.Function(P1)
    du, dp = ufl.TrialFunction(P2), ufl.TrialFunction(P1)
    v, q = ufl.TestFunction(P2), ufl.TestFunction(P1)

    F = [
        inner(ufl.grad(u), ufl.grad(v)) * dx + inner(p, ufl.div(v)) * dx,
        inner(ufl.div(u), q) * dx
    ]
    J = [[derivative(F[0], u, du),
          derivative(F[0], p, dp)],
         [derivative(F[1], u, du),
          derivative(F[1], p, dp)]]
    P = [[J[0][0], None], [None, inner(dp, q) * dx]]

    # -- Blocked and monolithic

    Jmat0 = dolfinx.fem.create_matrix_block(J)
    Pmat0 = dolfinx.fem.create_matrix_block(P)
    Fvec0 = dolfinx.fem.create_vector_block(F)

    snes = PETSc.SNES().create(dolfinx.MPI.comm_world)
    snes.setTolerances(rtol=1.0e-15, max_it=10)

    snes.getKSP().setType("minres")
    snes.getKSP().getPC().setType("lu")
    snes.getKSP().getPC().setFactorSolverType("mumps")

    problem = NonlinearPDE_SNESProblem(F, J, [u, p], bcs, P=P)
    snes.setFunction(problem.F_block, Fvec0)
    snes.setJacobian(problem.J_block, J=Jmat0, P=Pmat0)

    u.interpolate(initial_guess_u)
    p.interpolate(initial_guess_p)

    x0 = dolfinx.fem.create_vector_block(F)
    with u.vector.localForm() as _u, p.vector.localForm() as _p:
        dolfinx.cpp.la.scatter_local_vectors(x0, [_u.array_r, _p.array_r], [
            u.function_space.dofmap.index_map,
            p.function_space.dofmap.index_map
        ])
    x0.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                   mode=PETSc.ScatterMode.FORWARD)

    snes.solve(None, x0)

    assert snes.getConvergedReason() > 0

    # -- Blocked and nested

    Jmat1 = dolfinx.fem.create_matrix_nest(J)
    Pmat1 = dolfinx.fem.create_matrix_nest(P)
    Fvec1 = dolfinx.fem.create_vector_nest(F)

    snes = PETSc.SNES().create(dolfinx.MPI.comm_world)
    snes.setTolerances(rtol=1.0e-15, max_it=10)

    nested_IS = Jmat1.getNestISs()

    snes.getKSP().setType("minres")
    snes.getKSP().setTolerances(rtol=1e-12)
    snes.getKSP().getPC().setType("fieldsplit")
    snes.getKSP().getPC().setFieldSplitIS(["u", nested_IS[0][0]],
                                          ["p", nested_IS[1][1]])

    ksp_u, ksp_p = snes.getKSP().getPC().getFieldSplitSubKSP()
    ksp_u.setType("preonly")
    ksp_u.getPC().setType('lu')
    ksp_u.getPC().setFactorSolverType('mumps')
    ksp_p.setType("preonly")
    ksp_p.getPC().setType('lu')
    ksp_p.getPC().setFactorSolverType('mumps')

    problem = NonlinearPDE_SNESProblem(F, J, [u, p], bcs, P=P)
    snes.setFunction(problem.F_nest, Fvec1)
    snes.setJacobian(problem.J_nest, J=Jmat1, P=Pmat1)

    u.interpolate(initial_guess_u)
    p.interpolate(initial_guess_p)

    x1 = dolfinx.fem.create_vector_nest(F)
    for x1_soln_pair in zip(x1.getNestSubVecs(), (u, p)):
        x1_sub, soln_sub = x1_soln_pair
        soln_sub.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                                    mode=PETSc.ScatterMode.FORWARD)
        soln_sub.vector.copy(result=x1_sub)
        x1_sub.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                           mode=PETSc.ScatterMode.FORWARD)

    x1.set(0.0)
    snes.solve(None, x1)

    assert snes.getConvergedReason() > 0
    assert nest_matrix_norm(Jmat1) == pytest.approx(Jmat0.norm(), 1.0e-12)
    assert Fvec1.norm() == pytest.approx(Fvec0.norm(), 1.0e-12)
    assert x1.norm() == pytest.approx(x0.norm(), 1.0e-12)

    # -- Monolithic

    P2_el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2)
    P1_el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    TH = P2_el * P1_el
    W = dolfinx.FunctionSpace(mesh, TH)
    U = dolfinx.Function(W)
    dU = ufl.TrialFunction(W)
    u, p = ufl.split(U)
    du, dp = ufl.split(dU)
    v, q = ufl.TestFunctions(W)

    F = inner(ufl.grad(u), ufl.grad(v)) * dx + inner(p, ufl.div(v)) * dx \
        + inner(ufl.div(u), q) * dx
    J = derivative(F, U, dU)
    P = inner(ufl.grad(du), ufl.grad(v)) * dx + inner(dp, q) * dx

    bdofsW0_P2_0 = dolfinx.fem.locate_dofs_topological((W.sub(0), P2),
                                                       facetdim, bndry_facets0)
    bdofsW0_P2_1 = dolfinx.fem.locate_dofs_topological((W.sub(0), P2),
                                                       facetdim, bndry_facets1)

    bcs = [
        dolfinx.DirichletBC(u_bc_0, bdofsW0_P2_0, W.sub(0)),
        dolfinx.DirichletBC(u_bc_1, bdofsW0_P2_1, W.sub(0))
    ]

    Jmat2 = dolfinx.fem.create_matrix(J)
    Pmat2 = dolfinx.fem.create_matrix(P)
    Fvec2 = dolfinx.fem.create_vector(F)

    snes = PETSc.SNES().create(dolfinx.MPI.comm_world)
    snes.setTolerances(rtol=1.0e-15, max_it=10)

    snes.getKSP().setType("minres")
    snes.getKSP().getPC().setType("lu")
    snes.getKSP().getPC().setFactorSolverType("mumps")

    problem = NonlinearPDE_SNESProblem(F, J, U, bcs, P=P)
    snes.setFunction(problem.F_mono, Fvec2)
    snes.setJacobian(problem.J_mono, J=Jmat2, P=Pmat2)

    U.interpolate(lambda x: numpy.row_stack(
        (initial_guess_u(x), initial_guess_p(x))))

    x2 = dolfinx.fem.create_vector(F)
    x2.array = U.vector.array_r

    snes.solve(None, x2)

    assert snes.getConvergedReason() > 0
    assert Jmat2.norm() == pytest.approx(Jmat0.norm(), 1.0e-12)
    assert Fvec2.norm() == pytest.approx(Fvec0.norm(), 1.0e-12)
    assert x2.norm() == pytest.approx(x0.norm(), 1.0e-12)
예제 #26
0
def test_assembly_ds_domains(mesh):
    V = dolfinx.FunctionSpace(mesh, ("CG", 1))
    u, v = ufl.TrialFunction(V), ufl.TestFunction(V)

    def bottom(x):
        return numpy.isclose(x[1], 0.0)

    def top(x):
        return numpy.isclose(x[1], 1.0)

    def left(x):
        return numpy.isclose(x[0], 0.0)

    def right(x):
        return numpy.isclose(x[0], 1.0)

    bottom_facets = locate_entities_geometrical(mesh,
                                                mesh.topology.dim - 1,
                                                bottom,
                                                boundary_only=True)
    bottom_vals = numpy.full(bottom_facets.shape, 1, numpy.intc)

    top_facets = locate_entities_geometrical(mesh,
                                             mesh.topology.dim - 1,
                                             top,
                                             boundary_only=True)
    top_vals = numpy.full(top_facets.shape, 2, numpy.intc)

    left_facets = locate_entities_geometrical(mesh,
                                              mesh.topology.dim - 1,
                                              left,
                                              boundary_only=True)
    left_vals = numpy.full(left_facets.shape, 3, numpy.intc)

    right_facets = locate_entities_geometrical(mesh,
                                               mesh.topology.dim - 1,
                                               right,
                                               boundary_only=True)
    right_vals = numpy.full(right_facets.shape, 6, numpy.intc)

    indices = numpy.hstack(
        (bottom_facets, top_facets, left_facets, right_facets))
    values = numpy.hstack((bottom_vals, top_vals, left_vals, right_vals))

    indices, pos = numpy.unique(indices, return_index=True)
    marker = dolfinx.mesh.MeshTags(mesh, mesh.topology.dim - 1, indices,
                                   values[pos])

    ds = ufl.Measure('ds', subdomain_data=marker, domain=mesh)

    w = dolfinx.Function(V)
    with w.vector.localForm() as w_local:
        w_local.set(0.5)

    # Assemble matrix
    a = w * ufl.inner(u, v) * (ds(1) + ds(2) + ds(3) + ds(6))
    A = dolfinx.fem.assemble_matrix(a)
    A.assemble()
    norm1 = A.norm()
    a2 = w * ufl.inner(u, v) * ds
    A2 = dolfinx.fem.assemble_matrix(a2)
    A2.assemble()
    norm2 = A2.norm()
    assert norm1 == pytest.approx(norm2, 1.0e-12)

    # Assemble vector
    L = ufl.inner(w, v) * (ds(1) + ds(2) + ds(3) + ds(6))
    b = dolfinx.fem.assemble_vector(L)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    L2 = ufl.inner(w, v) * ds
    b2 = dolfinx.fem.assemble_vector(L2)
    b2.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    assert b.norm() == pytest.approx(b2.norm(), 1.0e-12)

    # Assemble scalar
    L = w * (ds(1) + ds(2) + ds(3) + ds(6))
    s = dolfinx.fem.assemble_scalar(L)
    s = mesh.mpi_comm().allreduce(s, op=MPI.SUM)
    L2 = w * ds
    s2 = dolfinx.fem.assemble_scalar(L2)
    s2 = mesh.mpi_comm().allreduce(s2, op=MPI.SUM)
    assert (s == pytest.approx(s2, 1.0e-12)
            and 2.0 == pytest.approx(s, 1.0e-12))
예제 #27
0
def test_assembly_solve_taylor_hood(mesh):
    """Assemble Stokes problem with Taylor-Hood elements and solve."""
    P2 = fem.VectorFunctionSpace(mesh, ("Lagrange", 2))
    P1 = fem.FunctionSpace(mesh, ("Lagrange", 1))

    def boundary0(x):
        """Define boundary x = 0"""
        return x[0] < 10 * numpy.finfo(float).eps

    def boundary1(x):
        """Define boundary x = 1"""
        return x[0] > (1.0 - 10 * numpy.finfo(float).eps)

    # Locate facets on boundaries
    facetdim = mesh.topology.dim - 1
    bndry_facets0 = dolfinx.mesh.locate_entities_boundary(
        mesh, facetdim, boundary0)
    bndry_facets1 = dolfinx.mesh.locate_entities_boundary(
        mesh, facetdim, boundary1)

    bdofs0 = dolfinx.fem.locate_dofs_topological(P2, facetdim, bndry_facets0)
    bdofs1 = dolfinx.fem.locate_dofs_topological(P2, facetdim, bndry_facets1)

    u0 = dolfinx.Function(P2)
    u0.vector.set(1.0)
    u0.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                          mode=PETSc.ScatterMode.FORWARD)

    bc0 = dolfinx.DirichletBC(u0, bdofs0)
    bc1 = dolfinx.DirichletBC(u0, bdofs1)

    u, p = ufl.TrialFunction(P2), ufl.TrialFunction(P1)
    v, q = ufl.TestFunction(P2), ufl.TestFunction(P1)

    a00 = inner(ufl.grad(u), ufl.grad(v)) * dx
    a01 = ufl.inner(p, ufl.div(v)) * dx
    a10 = ufl.inner(ufl.div(u), q) * dx
    a11 = None

    p00 = a00
    p01, p10 = None, None
    p11 = inner(p, q) * dx

    # FIXME
    # We need zero function for the 'zero' part of L
    p_zero = dolfinx.Function(P1)
    f = dolfinx.Function(P2)
    L0 = ufl.inner(f, v) * dx
    L1 = ufl.inner(p_zero, q) * dx

    def nested_solve():
        """Nested solver"""
        A = dolfinx.fem.assemble_matrix_nest([[a00, a01], [a10, a11]],
                                             [bc0, bc1],
                                             [["baij", "aij"], ["aij", ""]])
        A.assemble()
        P = dolfinx.fem.assemble_matrix_nest([[p00, p01], [p10, p11]],
                                             [bc0, bc1],
                                             [["aij", "aij"], ["aij", ""]])
        P.assemble()
        b = dolfinx.fem.assemble_vector_nest([L0, L1])
        dolfinx.fem.apply_lifting_nest(b, [[a00, a01], [a10, a11]], [bc0, bc1])
        for b_sub in b.getNestSubVecs():
            b_sub.ghostUpdate(addv=PETSc.InsertMode.ADD,
                              mode=PETSc.ScatterMode.REVERSE)
        bcs = dolfinx.cpp.fem.bcs_rows(
            dolfinx.fem.assemble._create_cpp_form([L0, L1]), [bc0, bc1])
        dolfinx.fem.set_bc_nest(b, bcs)
        b.assemble()

        ksp = PETSc.KSP()
        ksp.create(mesh.mpi_comm())
        ksp.setOperators(A, P)
        nested_IS = P.getNestISs()
        ksp.setType("minres")
        pc = ksp.getPC()
        pc.setType("fieldsplit")
        pc.setFieldSplitIS(["u", nested_IS[0][0]], ["p", nested_IS[1][1]])
        ksp_u, ksp_p = pc.getFieldSplitSubKSP()
        ksp_u.setType("preonly")
        ksp_u.getPC().setType('lu')
        ksp_p.setType("preonly")

        def monitor(ksp, its, rnorm):
            # print("Num it, rnorm:", its, rnorm)
            pass

        ksp.setTolerances(rtol=1.0e-8, max_it=50)
        ksp.setMonitor(monitor)
        ksp.setFromOptions()
        x = b.copy()
        ksp.solve(b, x)
        assert ksp.getConvergedReason() > 0
        return b.norm(), x.norm(), nest_matrix_norm(A), nest_matrix_norm(P)

    def blocked_solve():
        """Blocked (monolithic) solver"""
        A = dolfinx.fem.assemble_matrix_block([[a00, a01], [a10, a11]],
                                              [bc0, bc1])
        A.assemble()
        P = dolfinx.fem.assemble_matrix_block([[p00, p01], [p10, p11]],
                                              [bc0, bc1])
        P.assemble()
        b = dolfinx.fem.assemble_vector_block([L0, L1],
                                              [[a00, a01], [a10, a11]],
                                              [bc0, bc1])

        ksp = PETSc.KSP()
        ksp.create(mesh.mpi_comm())
        ksp.setOperators(A, P)
        ksp.setType("minres")
        pc = ksp.getPC()
        pc.setType('lu')
        ksp.setTolerances(rtol=1.0e-8, max_it=50)
        ksp.setFromOptions()
        x = A.createVecRight()
        ksp.solve(b, x)
        assert ksp.getConvergedReason() > 0
        return b.norm(), x.norm(), A.norm(), P.norm()

    def monolithic_solve():
        """Monolithic (interleaved) solver"""
        P2_el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2)
        P1_el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
        TH = P2_el * P1_el
        W = dolfinx.FunctionSpace(mesh, TH)
        (u, p) = ufl.TrialFunctions(W)
        (v, q) = ufl.TestFunctions(W)
        a00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx
        a01 = ufl.inner(p, ufl.div(v)) * dx
        a10 = ufl.inner(ufl.div(u), q) * dx
        a = a00 + a01 + a10

        p00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx
        p11 = ufl.inner(p, q) * dx
        p_form = p00 + p11

        f = dolfinx.Function(W.sub(0).collapse())
        p_zero = dolfinx.Function(W.sub(1).collapse())
        L0 = inner(f, v) * dx
        L1 = inner(p_zero, q) * dx
        L = L0 + L1

        bdofsW0_P2_0 = dolfinx.fem.locate_dofs_topological(
            (W.sub(0), P2), facetdim, bndry_facets0)
        bdofsW0_P2_1 = dolfinx.fem.locate_dofs_topological(
            (W.sub(0), P2), facetdim, bndry_facets1)

        bc0 = dolfinx.DirichletBC(u0, bdofsW0_P2_0, W.sub(0))
        bc1 = dolfinx.DirichletBC(u0, bdofsW0_P2_1, W.sub(0))

        A = dolfinx.fem.assemble_matrix(a, [bc0, bc1])
        A.assemble()
        P = dolfinx.fem.assemble_matrix(p_form, [bc0, bc1])
        P.assemble()

        b = dolfinx.fem.assemble_vector(L)
        dolfinx.fem.apply_lifting(b, [a], [[bc0, bc1]])
        b.ghostUpdate(addv=PETSc.InsertMode.ADD,
                      mode=PETSc.ScatterMode.REVERSE)
        dolfinx.fem.set_bc(b, [bc0, bc1])

        ksp = PETSc.KSP()
        ksp.create(mesh.mpi_comm())
        ksp.setOperators(A, P)
        ksp.setType("minres")
        pc = ksp.getPC()
        pc.setType('lu')

        def monitor(ksp, its, rnorm):
            # print("Num it, rnorm:", its, rnorm)
            pass

        ksp.setTolerances(rtol=1.0e-8, max_it=50)
        ksp.setMonitor(monitor)
        ksp.setFromOptions()
        x = A.createVecRight()
        ksp.solve(b, x)
        assert ksp.getConvergedReason() > 0
        return b.norm(), x.norm(), A.norm(), P.norm()

    bnorm0, xnorm0, Anorm0, Pnorm0 = nested_solve()
    bnorm1, xnorm1, Anorm1, Pnorm1 = blocked_solve()
    bnorm2, xnorm2, Anorm2, Pnorm2 = monolithic_solve()

    assert bnorm1 == pytest.approx(bnorm0, 1.0e-12)
    assert xnorm1 == pytest.approx(xnorm0, 1.0e-8)
    assert Anorm1 == pytest.approx(Anorm0, 1.0e-12)
    assert Pnorm1 == pytest.approx(Pnorm0, 1.0e-12)

    assert bnorm2 == pytest.approx(bnorm0, 1.0e-12)
    assert xnorm2 == pytest.approx(xnorm0, 1.0e-8)
    assert Anorm2 == pytest.approx(Anorm0, 1.0e-12)
    assert Pnorm2 == pytest.approx(Pnorm0, 1.0e-12)
예제 #28
0
def test_assembly_solve_block(mode):
    """Solve a two-field mass-matrix like problem with block matrix approaches
    and test that solution is the same.
    """
    mesh = UnitSquareMesh(MPI.COMM_WORLD, 32, 31, ghost_mode=mode)
    P = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    V0 = dolfinx.fem.FunctionSpace(mesh, P)
    V1 = V0.clone()

    def boundary(x):
        return numpy.logical_or(x[0] < 1.0e-6, x[0] > 1.0 - 1.0e-6)

    # Locate facets on boundary
    facetdim = mesh.topology.dim - 1
    bndry_facets = dolfinx.mesh.locate_entities_boundary(
        mesh, facetdim, boundary)

    bdofsV0 = dolfinx.fem.locate_dofs_topological(V0, facetdim, bndry_facets)
    bdofsV1 = dolfinx.fem.locate_dofs_topological(V1, facetdim, bndry_facets)

    u_bc0 = dolfinx.fem.Function(V0)
    u_bc0.vector.set(50.0)
    u_bc0.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                             mode=PETSc.ScatterMode.FORWARD)
    u_bc1 = dolfinx.fem.Function(V1)
    u_bc1.vector.set(20.0)
    u_bc1.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                             mode=PETSc.ScatterMode.FORWARD)
    bcs = [
        dolfinx.fem.dirichletbc.DirichletBC(u_bc0, bdofsV0),
        dolfinx.fem.dirichletbc.DirichletBC(u_bc1, bdofsV1)
    ]

    # Variational problem
    u, p = ufl.TrialFunction(V0), ufl.TrialFunction(V1)
    v, q = ufl.TestFunction(V0), ufl.TestFunction(V1)
    f = 1.0
    g = -3.0
    zero = dolfinx.Function(V0)

    a00 = inner(u, v) * dx
    a01 = zero * inner(p, v) * dx
    a10 = zero * inner(u, q) * dx
    a11 = inner(p, q) * dx
    L0 = inner(f, v) * dx
    L1 = inner(g, q) * dx

    def monitor(ksp, its, rnorm):
        pass
        # print("Norm:", its, rnorm)

    A0 = dolfinx.fem.assemble_matrix_block([[a00, a01], [a10, a11]], bcs)
    b0 = dolfinx.fem.assemble_vector_block([L0, L1], [[a00, a01], [a10, a11]],
                                           bcs)
    A0.assemble()
    A0norm = A0.norm()
    b0norm = b0.norm()
    x0 = A0.createVecLeft()
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setOperators(A0)
    ksp.setMonitor(monitor)
    ksp.setType('cg')
    ksp.setTolerances(rtol=1.0e-14)
    ksp.setFromOptions()
    ksp.solve(b0, x0)
    x0norm = x0.norm()

    # Nested (MatNest)
    A1 = dolfinx.fem.assemble_matrix_nest([[a00, a01], [a10, a11]],
                                          bcs,
                                          diagonal=1.0)
    A1.assemble()
    b1 = dolfinx.fem.assemble_vector_nest([L0, L1])
    dolfinx.fem.apply_lifting_nest(b1, [[a00, a01], [a10, a11]], bcs)
    for b_sub in b1.getNestSubVecs():
        b_sub.ghostUpdate(addv=PETSc.InsertMode.ADD,
                          mode=PETSc.ScatterMode.REVERSE)
    bcs0 = dolfinx.cpp.fem.bcs_rows(
        dolfinx.fem.assemble._create_cpp_form([L0, L1]), bcs)
    dolfinx.fem.set_bc_nest(b1, bcs0)
    b1.assemble()

    b1norm = b1.norm()
    assert b1norm == pytest.approx(b0norm, 1.0e-12)
    A1norm = nest_matrix_norm(A1)
    assert A0norm == pytest.approx(A1norm, 1.0e-12)

    x1 = b1.copy()
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setMonitor(monitor)
    ksp.setOperators(A1)
    ksp.setType('cg')
    ksp.setTolerances(rtol=1.0e-12)
    ksp.setFromOptions()
    ksp.solve(b1, x1)
    x1norm = x1.norm()
    assert x1norm == pytest.approx(x0norm, rel=1.0e-12)

    # Monolithic version
    E = P * P
    W = dolfinx.fem.FunctionSpace(mesh, E)
    u0, u1 = ufl.TrialFunctions(W)
    v0, v1 = ufl.TestFunctions(W)
    a = inner(u0, v0) * dx + inner(u1, v1) * dx
    L = inner(f, v0) * ufl.dx + inner(g, v1) * dx

    u0_bc = dolfinx.fem.Function(V0)
    u0_bc.vector.set(50.0)
    u0_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                             mode=PETSc.ScatterMode.FORWARD)
    u1_bc = dolfinx.fem.Function(V1)
    u1_bc.vector.set(20.0)
    u1_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                             mode=PETSc.ScatterMode.FORWARD)

    bdofsW0_V0 = dolfinx.fem.locate_dofs_topological((W.sub(0), V0), facetdim,
                                                     bndry_facets)
    bdofsW1_V1 = dolfinx.fem.locate_dofs_topological((W.sub(1), V1), facetdim,
                                                     bndry_facets)

    bcs = [
        dolfinx.fem.dirichletbc.DirichletBC(u0_bc, bdofsW0_V0, W.sub(0)),
        dolfinx.fem.dirichletbc.DirichletBC(u1_bc, bdofsW1_V1, W.sub(1))
    ]

    A2 = dolfinx.fem.assemble_matrix(a, bcs)
    A2.assemble()
    b2 = dolfinx.fem.assemble_vector(L)
    dolfinx.fem.apply_lifting(b2, [a], [bcs])
    b2.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    dolfinx.fem.set_bc(b2, bcs)
    A2norm = A2.norm()
    b2norm = b2.norm()
    assert A2norm == pytest.approx(A0norm, 1.0e-12)
    assert b2norm == pytest.approx(b0norm, 1.0e-12)

    x2 = b2.copy()
    ksp = PETSc.KSP()
    ksp.create(mesh.mpi_comm())
    ksp.setMonitor(monitor)
    ksp.setOperators(A2)
    ksp.setType('cg')
    ksp.getPC().setType('jacobi')
    ksp.setTolerances(rtol=1.0e-12)
    ksp.setFromOptions()
    ksp.solve(b2, x2)
    x2norm = x2.norm()
    assert x2norm == pytest.approx(x0norm, 1.0e-10)
예제 #29
0
def test_matrix_assembly_block(mode):
    """Test assembly of block matrices and vectors into (a) monolithic
    blocked structures, PETSc Nest structures, and monolithic structures.
    """
    mesh = UnitSquareMesh(MPI.COMM_WORLD, 4, 8, ghost_mode=mode)

    p0, p1 = 1, 2
    P0 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), p0)
    P1 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), p1)

    V0 = dolfinx.fem.FunctionSpace(mesh, P0)
    V1 = dolfinx.fem.FunctionSpace(mesh, P1)

    def boundary(x):
        return numpy.logical_or(x[0] < 1.0e-6, x[0] > 1.0 - 1.0e-6)

    # Locate facets on boundary
    facetdim = mesh.topology.dim - 1
    bndry_facets = dolfinx.mesh.locate_entities_boundary(
        mesh, facetdim, boundary)

    bdofsV1 = dolfinx.fem.locate_dofs_topological(V1, facetdim, bndry_facets)

    u_bc = dolfinx.fem.Function(V1)
    with u_bc.vector.localForm() as u_local:
        u_local.set(50.0)
    bc = dolfinx.fem.dirichletbc.DirichletBC(u_bc, bdofsV1)

    # Define variational problem
    u, p = ufl.TrialFunction(V0), ufl.TrialFunction(V1)
    v, q = ufl.TestFunction(V0), ufl.TestFunction(V1)
    f = 1.0
    g = -3.0
    zero = dolfinx.Function(V0)

    a00 = inner(u, v) * dx
    a01 = inner(p, v) * dx
    a10 = inner(u, q) * dx
    a11 = inner(p, q) * dx

    L0 = zero * inner(f, v) * dx
    L1 = inner(g, q) * dx

    a_block = [[a00, a01], [a10, a11]]
    L_block = [L0, L1]

    # Monolithic blocked
    A0 = dolfinx.fem.assemble_matrix_block(a_block, [bc])
    A0.assemble()
    b0 = dolfinx.fem.assemble_vector_block(L_block, a_block, [bc])
    assert A0.getType() != "nest"
    Anorm0 = A0.norm()
    bnorm0 = b0.norm()

    # Nested (MatNest)
    A1 = dolfinx.fem.assemble_matrix_nest(a_block, [bc],
                                          [["baij", "aij"], ["aij", ""]])
    A1.assemble()
    Anorm1 = nest_matrix_norm(A1)
    assert Anorm0 == pytest.approx(Anorm1, 1.0e-12)

    b1 = dolfinx.fem.assemble_vector_nest(L_block)
    dolfinx.fem.apply_lifting_nest(b1, a_block, [bc])
    for b_sub in b1.getNestSubVecs():
        b_sub.ghostUpdate(addv=PETSc.InsertMode.ADD,
                          mode=PETSc.ScatterMode.REVERSE)
    bcs0 = dolfinx.cpp.fem.bcs_rows(
        dolfinx.fem.assemble._create_cpp_form(L_block), [bc])
    dolfinx.fem.set_bc_nest(b1, bcs0)
    b1.assemble()

    bnorm1 = math.sqrt(sum([x.norm()**2 for x in b1.getNestSubVecs()]))
    assert bnorm0 == pytest.approx(bnorm1, 1.0e-12)

    # Monolithic version
    E = P0 * P1
    W = dolfinx.fem.FunctionSpace(mesh, E)
    u0, u1 = ufl.TrialFunctions(W)
    v0, v1 = ufl.TestFunctions(W)
    a = inner(u0, v0) * dx + inner(u1, v1) * dx + inner(u0, v1) * dx + inner(
        u1, v0) * dx
    L = zero * inner(f, v0) * ufl.dx + inner(g, v1) * dx

    bdofsW_V1 = dolfinx.fem.locate_dofs_topological(
        (W.sub(1), V1), mesh.topology.dim - 1, bndry_facets)
    bc = dolfinx.fem.dirichletbc.DirichletBC(u_bc, bdofsW_V1, W.sub(1))
    A2 = dolfinx.fem.assemble_matrix(a, [bc])
    A2.assemble()
    b2 = dolfinx.fem.assemble_vector(L)
    dolfinx.fem.apply_lifting(b2, [a], [[bc]])
    b2.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    dolfinx.fem.set_bc(b2, [bc])
    assert A2.getType() != "nest"
    assert A2.norm() == pytest.approx(Anorm0, 1.0e-9)
    assert b2.norm() == pytest.approx(bnorm0, 1.0e-9)
예제 #30
0
def test_custom_mesh_loop_rank1():

    # Create mesh and function space
    mesh = dolfinx.generation.UnitSquareMesh(MPI.COMM_WORLD, 64, 64)
    V = dolfinx.FunctionSpace(mesh, ("Lagrange", 1))

    # Unpack mesh and dofmap data
    num_owned_cells = mesh.topology.index_map(mesh.topology.dim).size_local
    num_cells = num_owned_cells + mesh.topology.index_map(mesh.topology.dim).num_ghosts
    x_dofs = mesh.geometry.dofmap.array.reshape(num_cells, 3)
    x = mesh.geometry.x
    dofmap = V.dofmap.list.array.reshape(num_cells, 3)
    dofmap_t = dolfinx.cpp.fem.transpose_dofmap(V.dofmap.list, num_owned_cells)

    # Assemble with pure Numba function (two passes, first will include
    # JIT overhead)
    b0 = dolfinx.Function(V)
    for i in range(2):
        with b0.vector.localForm() as b:
            b.set(0.0)
            start = time.time()
            assemble_vector(np.asarray(b), (x_dofs, x), dofmap, num_owned_cells)
            end = time.time()
            print("Time (numba, pass {}): {}".format(i, end - start))
    b0.vector.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    assert b0.vector.sum() == pytest.approx(1.0)

    # Assemble with pure Numba function using parallel loop (two passes,
    # first will include JIT overhead)
    btmp = dolfinx.Function(V)
    for i in range(2):
        with btmp.vector.localForm() as b:
            b.set(0.0)
            start = time.time()
            assemble_vector_parallel(np.asarray(b), x_dofs, x,
                                     dofmap_t.array, dofmap_t.offsets,
                                     num_owned_cells)
            end = time.time()
            print("Time (numba parallel, pass {}): {}".format(i, end - start))
    btmp.vector.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    assert (btmp.vector - b0.vector).norm() == pytest.approx(0.0)

    # Test against generated code and general assembler
    v = ufl.TestFunction(V)
    L = inner(1.0, v) * dx
    start = time.time()
    b1 = dolfinx.fem.assemble_vector(L)
    end = time.time()
    print("Time (C++, pass 0):", end - start)

    with b1.localForm() as b_local:
        b_local.set(0.0)
    start = time.time()
    dolfinx.fem.assemble_vector(b1, L)
    end = time.time()
    print("Time (C++, pass 1):", end - start)
    b1.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    assert (b1 - b0.vector).norm() == pytest.approx(0.0)

    # Assemble using generated tabulate_tensor kernel and Numba assembler
    b3 = dolfinx.Function(V)
    ufc_form, module, code = dolfinx.jit.ffcx_jit(mesh.mpi_comm(), L)

    # First 0 for "cell" integrals, second 0 for the first one, i.e. default domain
    kernel = ufc_form.integrals(0)[0].tabulate_tensor
    for i in range(2):
        with b3.vector.localForm() as b:
            b.set(0.0)
            start = time.time()
            assemble_vector_ufc(np.asarray(b), kernel, (x_dofs, x), dofmap, num_owned_cells)
            end = time.time()
            print("Time (numba/cffi, pass {}): {}".format(i, end - start))
    b3.vector.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    assert (b3.vector - b0.vector).norm() == pytest.approx(0.0)