def amg_solve(N, method): # Elasticity parameters E = 1.0e9 nu = 0.3 mu = E / (2.0 * (1.0 + nu)) lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)) # Stress computation def sigma(v): return 2.0 * mu * sym(grad(v)) + lmbda * tr(sym( grad(v))) * Identity(2) # Define problem mesh = UnitSquareMesh(MPI.comm_world, N, N) V = VectorFunctionSpace(mesh, 'Lagrange', 1) bc0 = Function(V) with bc0.vector().localForm() as bc_local: bc_local.set(0.0) def boundary(x, only_boundary): return [only_boundary] * x.shape(0) bc = DirichletBC(V.sub(0), bc0, boundary) u = TrialFunction(V) v = TestFunction(V) # Forms a, L = inner(sigma(u), grad(v)) * dx, dot(ufl.as_vector( (1.0, 1.0)), v) * dx # Assemble linear algebra objects A = assemble_matrix(a, [bc]) A.assemble() b = assemble_vector(L) apply_lifting(b, [a], [[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) # Create solution function u = Function(V) # Create near null space basis and orthonormalize null_space = build_nullspace(V, u.vector()) # Attached near-null space to matrix A.set_near_nullspace(null_space) # Test that basis is orthonormal assert null_space.is_orthonormal() # Create PETSC smoothed aggregation AMG preconditioner, and # create CG solver solver = PETScKrylovSolver("cg", method) # Set matrix operator solver.set_operator(A) # Compute solution and return number of iterations return solver.solve(u.vector(), b)
def F(self, snes, x, F): """Assemble residual vector.""" x.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) x.copy(self.u.vector()) self.u.vector().ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) with F.localForm() as f_local: f_local.set(0.0) fem.assemble_vector(F, self.L) fem.apply_lifting(F, [self.a], [[self.bc]], [x], -1.0) F.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) fem.set_bc(F, [self.bc], x, -1.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_vector(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 = fem.assemble_matrix(a._cpp_object, bcs) A.assemble() comm = L._cpp_object.mesh().mpi_comm() ksp = PETSc.KSP().create(comm) ksp.setOperators(A) ksp.setOptionsPrefix("dolfin_solve_") opts = PETSc.Options() opts.prefixPush("dolfin_solve_") for k, v in petsc_options.items(): opts[k] = v opts.prefixPop() ksp.setFromOptions() ksp.solve(b, u.vector) ksp.view() # Solve nonlinear variational problem else: raise RuntimeError("Not implemented")
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")
u0 = Function(V) with u0.vector.localForm() as bc_local: bc_local.set(0.0) # Set up boundary condition on inner surface bc = DirichletBC(V, u0, boundary) # Assemble system, applying boundary conditions and preserving symmetry) A = assemble_matrix(a, [bc]) A.assemble() b = assemble_vector(L) apply_lifting(b, [a], [[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) # Create solution function u = Function(V) # Create near null space basis (required for smoothed aggregation AMG). null_space = build_nullspace(V) # Attach near nullspace to matrix A.setNearNullSpace(null_space) # Set solver options opts = PETSc.Options() opts["ksp_type"] = "cg" opts["ksp_rtol"] = 1.0e-12 opts["pc_type"] = "gamg"
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 project(v, V=None, bcs=[], mesh=None, funct=None): """Return projection of given expression *v* onto the finite element space *V*. *Arguments* v a :py:class:`Function <dolfin.functions.function.Function>` or an :py:class:`Expression <dolfin.functions.expression.Expression>` bcs Optional argument :py:class:`list of DirichletBC <dolfin.fem.bcs.DirichletBC>` V Optional argument :py:class:`FunctionSpace <dolfin.functions.functionspace.FunctionSpace>` mesh Optional argument :py:class:`mesh <dolfin.cpp.Mesh>`. funct Target function where result is stored. *Example of usage* .. code-block:: python v = Expression("sin(pi*x[0])") V = FunctionSpace(mesh, "Lagrange", 1) Pv = project(v, V) This is useful for post-processing functions or expressions which are not readily handled by visualization tools (such as for example discontinuous functions). """ # Try figuring out a function space if not specified if V is None: # Create function space based on Expression element if trying # to project an Expression if isinstance(v, function.Expression): if mesh is not None and isinstance(mesh, cpp.mesh.Mesh): V = function.FunctionSpace(mesh, v.ufl_element()) # else: # cpp.dolfin_error("projection.py", # "perform projection", # "Expected a mesh when projecting an Expression") else: # Otherwise try extracting function space from expression V = _extract_function_space(v, mesh) # Check arguments # Ensure we have a mesh and attach to measure if mesh is None: mesh = V.mesh dx = ufl.dx(mesh) # Define variational problem for projection w = function.TestFunction(V) Pv = function.TrialFunction(V) a = ufl.inner(Pv, w) * dx L = ufl.inner(v, w) * dx # Assemble linear system A = fem.assemble_matrix(a, bcs) A.assemble() b = fem.assemble_vector(L) fem.apply_lifting(b, [a], [bcs]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) fem.set_bc(b, bcs) # Solve linear system for projection if funct is None: funct = function.Function(V) la.solve(A, funct.vector, b) return funct