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)
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
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
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")
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
def J(self, snes, x, J, P): """Assemble Jacobian matrix.""" fem.assemble(J, self.a, [self.bc])
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])