Beispiel #1
0
 def F(self, snes, x, F):
     """Assemble residual vector."""
     _F = dolfin.cpp.la.PETScVector(F)
     _x = dolfin.cpp.la.PETScVector(x)
     _x.update_ghosts()
     x.copy(self.u.vector().vec())
     self.u.vector().update_ghosts()
     fem.assemble(_F, self.L, [self.a], [self.bc], _x)
Beispiel #2
0
 def J(self, x):
     """Assemble Jacobian matrix."""
     if self._J is None:
         self._J = fem.assemble_matrix([[self.a]], [self.bc],
                                       dolfin.cpp.fem.BlockType.monolithic)
     else:
         self._J = fem.assemble(self._J, self.a, [self.bc])
     return self._J
Beispiel #3
0
 def F(self, x):
     """Assemble residual vector."""
     if self._F is None:
         self._F = fem.assemble_vector([self.L], [[self.a]], [self.bc],
                                       dolfin.cpp.fem.BlockType.monolithic,
                                       x)
     else:
         self._F = fem.assemble(self._F, self.L, [self.a], [self.bc], x)
     return self._F
def test_krylov_solver_lu():

    mesh = UnitSquareMesh(MPI.comm_world, 12, 12)
    V = FunctionSpace(mesh, ("Lagrange", 1))
    u, v = TrialFunction(V), TestFunction(V)

    a = Constant(1.0) * inner(u, v) * dx
    L = inner(Constant(1.0), v) * dx
    A = assemble(a)
    b = assemble(L)

    norm = 13.0

    solver = PETScKrylovSolver(mesh.mpi_comm())
    solver.set_options_prefix("test_lu_")
    PETScOptions.set("test_lu_ksp_type", "preonly")
    PETScOptions.set("test_lu_pc_type", "lu")
    solver.set_from_options()
    x = PETScVector()
    solver.set_operator(A)
    solver.solve(x, b)

    # *Tight* tolerance for LU solves
    assert round(x.norm(cpp.la.Norm.l2) - norm, 12) == 0
Beispiel #5
0
def _solve_varproblem(*args, **kwargs):
    "Solve variational problem a == L or F == 0"

    # Extract arguments
    eq, u, bcs, J, tol, M, form_compiler_parameters, petsc_options \
        = _extract_args(*args, **kwargs)

    # Solve linear variational problem
    if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form):

        a = fem.Form(eq.lhs, form_compiler_parameters=form_compiler_parameters)
        L = fem.Form(eq.rhs, form_compiler_parameters=form_compiler_parameters)

        b = fem.assemble(L._cpp_object)
        fem.apply_lifting(b, [a._cpp_object], [bcs])
        b.ghostUpdate(addv=PETSc.InsertMode.ADD,
                      mode=PETSc.ScatterMode.REVERSE)
        fem.set_bc(b, bcs)

        A = cpp.fem.create_matrix(a._cpp_object)
        A.zeroEntries()
        A = fem.assemble_matrix(a._cpp_object, bcs)
        A.assemble()

        comm = L._cpp_object.mesh().mpi_comm()
        solver = cpp.la.PETScKrylovSolver(comm)

        solver.set_options_prefix("dolfin_solve_")
        for k, v in petsc_options.items():
            cpp.la.PETScOptions.set("dolfin_solve_" + k, v)
        solver.set_from_options()

        solver.set_operator(A)
        solver.solve(u.vector(), b)

    # Solve nonlinear variational problem
    else:

        raise RuntimeError("Not implemented")
Beispiel #6
0
def assemble_system(A_form,
                    b_form,
                    bcs=None,
                    x0=None,
                    form_compiler_parameters=None,
                    A_tensor=None,
                    b_tensor=None,
                    backend=None):
    """Assemble form(s) and apply any given boundary conditions in a
    symmetric fashion and return tensor(s).

    The standard application of boundary conditions does not
    necessarily preserve the symmetry of the assembled matrix. In
    order to perserve symmetry in a system of equations with boundary
    conditions, one may use the alternative assemble_system instead of
    multiple calls to :py:func:`assemble
    <dolfin.fem.assembling.assemble>`.

    *Examples of usage*

       For instance, the statements

       .. code-block:: python

           A = assemble(a)
           b = assemble(L)
           bc.apply(A, b)

       can alternatively be carried out by

       .. code-block:: python

           A, b = assemble_system(a, L, bc)

       The statement above is valid even if ``bc`` is a list of
       :py:class:`DirichletBC <dolfin.fem.bcs.DirichletBC>`
       instances. For more info and options, see :py:func:`assemble
       <dolfin.fem.assembling.assemble>`.

    """
    # Create dolfin Form objects referencing all data needed by
    # assembler
    A_dolfin_form = _create_cpp_form(A_form, form_compiler_parameters)
    b_dolfin_form = _create_cpp_form(b_form, form_compiler_parameters)

    # A_tensor = fem.assemble(A_form)
    # b_tensor = fem.assemble(b_form)

    # Create tensors
    if A_tensor is None:
        A_tensor = cpp.fem.create_matrix(A_dolfin_form)
    if b_tensor is None:
        b_tensor = cpp.la.create_vector(
            b_dolfin_form.function_space(0).dofmap().index_map())

    # Check bcs
    bcs = _wrap_in_list(bcs, 'bcs', cpp.fem.DirichletBC)

    fem.assemble(b_tensor, b_form)
    fem.apply_lifting(b_tensor, [A_form], [bcs])
    b_tensor.ghostUpdate(addv=PETSc.InsertMode.ADD,
                         mode=PETSc.ScatterMode.REVERSE)
    fem.set_bc(b_tensor, bcs)

    fem.assemble(A_tensor, A_form, bcs)

    return A_tensor, b_tensor
def test_krylov_reuse_pc():
    "Test preconditioner re-use with PETScKrylovSolver"

    # Define problem
    mesh = UnitSquareMesh(MPI.comm_world, 8, 8)
    V = FunctionSpace(mesh, ('Lagrange', 1))
    bc = DirichletBC(V, Constant(0.0), lambda x, on_boundary: on_boundary)
    u = TrialFunction(V)
    v = TestFunction(V)

    # Forms
    a, L = inner(grad(u), grad(v)) * dx, dot(Constant(1.0), v) * dx

    A, P = PETScMatrix(), PETScMatrix()
    b = PETScVector()

    # Assemble linear algebra objects
    assemble(a, tensor=A)  # noqa
    assemble(a, tensor=P)  # noqa
    assemble(L, tensor=b)  # noqa

    # Apply boundary conditions
    bc.apply(A)
    bc.apply(P)
    bc.apply(b)

    # Create Krysolv solver and set operators
    solver = PETScKrylovSolver("gmres", "bjacobi")
    solver.set_operators(A, P)

    # Solve
    x = PETScVector()
    num_iter_ref = solver.solve(x, b)

    # Change preconditioner matrix (bad matrix) and solve (PC will be
    # updated)
    a_p = u * v * dx
    assemble(a_p, tensor=P)  # noqa
    bc.apply(P)
    x = PETScVector()
    num_iter_mod = solver.solve(x, b)
    assert num_iter_mod > num_iter_ref

    # Change preconditioner matrix (good matrix) and solve (PC will be
    # updated)
    a_p = a
    assemble(a_p, tensor=P)  # noqa
    bc.apply(P)
    x = PETScVector()
    num_iter = solver.solve(x, b)
    assert num_iter == num_iter_ref

    # Change preconditioner matrix (bad matrix) and solve (PC will not
    # be updated)
    solver.set_reuse_preconditioner(True)
    a_p = u * v * dx
    assemble(a_p, tensor=P)  # noqa
    bc.apply(P)
    x = PETScVector()
    num_iter = solver.solve(x, b)
    assert num_iter == num_iter_ref

    # Update preconditioner (bad PC, will increase iteration count)
    solver.set_reuse_preconditioner(False)
    x = PETScVector()
    num_iter = solver.solve(x, b)
    assert num_iter == num_iter_mod
Beispiel #8
0
 def J(self, snes, x, J, P):
     """Assemble Jacobian matrix."""
     fem.assemble(J, self.a, [self.bc])
Beispiel #9
0
 def J(self, snes, x, J, P):
     """Assemble Jacobian matrix."""
     _J = dolfin.cpp.la.PETScMatrix(J)
     # _x = dolfin.cpp.la.PETScVector(x)
     fem.assemble(_J, self.a, [self.bc])