def test_nullspace_check(mesh, degree): V = VectorFunctionSpace(mesh, ('Lagrange', degree)) u, v = TrialFunction(V), TestFunction(V) mesh.geometry.coord_mapping = fem.create_coordinate_map(mesh) E, nu = 2.0e2, 0.3 mu = E / (2.0 * (1.0 + nu)) lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)) def sigma(w, gdim): return 2.0 * mu * ufl.sym(grad(w)) + lmbda * ufl.tr( grad(w)) * ufl.Identity(gdim) a = inner(sigma(u, mesh.geometry.dim), grad(v)) * dx zero = Function(V) L = inner(zero, v) * dx # Assemble matrix and create compatible vector A, L = assembling.assemble_system(a, L, []) # Create null space basis and test null_space = build_elastic_nullspace(V) assert null_space.in_nullspace(A, tol=1.0e-8) null_space.orthonormalize() assert null_space.in_nullspace(A, tol=1.0e-8) # Create incorrect null space basis and test null_space = build_broken_elastic_nullspace(V) assert not null_space.in_nullspace(A, tol=1.0e-8) null_space.orthonormalize() assert not null_space.in_nullspace(A, tol=1.0e-8)
def test_mg_solver_laplace(): # Create meshes and function spaces meshes = [UnitSquareMesh(N, N) for N in [16, 32, 64]] V = [FunctionSpace(mesh, "Lagrange", 1) for mesh in meshes] # Create variational problem on fine grid u, v = TrialFunction(V[-1]), TestFunction(V[-1]) a = dot(grad(u), grad(v)) * dx L = v * dx bc0 = Function(V[-1]) bc = DirichletBC(V[-1], bc0, "on_boundary") A, b = assemble_system(a, L, bc) # Create collection of PETSc DM objects dm_collection = PETScDMCollection(V) # Create PETSc Krylov solver and set operator solver = PETScKrylovSolver() solver.set_operator(A) # Set PETSc solver type PETScOptions.set("ksp_type", "richardson") PETScOptions.set("pc_type", "mg") # Set PETSc MG type and levels PETScOptions.set("pc_mg_levels", len(V)) PETScOptions.set("pc_mg_galerkin") # Set smoother PETScOptions.set("mg_levels_ksp_type", "chebyshev") PETScOptions.set("mg_levels_pc_type", "jacobi") # Set tolerance and monitor residual PETScOptions.set("ksp_monitor_true_residual") PETScOptions.set("ksp_atol", 1.0e-12) PETScOptions.set("ksp_rtol", 1.0e-12) solver.set_from_options() # Get fine grid DM and attach fine grid DM to solver solver.set_dm(dm_collection.get_dm(-1)) solver.set_dm_active(False) # Solve x = PETScVector() solver.solve(x, b) # Check multigrid solution against LU solver solution solver = LUSolver(A) # noqa x_lu = PETScVector() solver.solve(x_lu, b) assert round((x - x_lu).norm("l2"), 10) == 0 # Clear all PETSc options from petsc4py import PETSc opts = PETSc.Options() for key in opts.getAll(): opts.delValue(key)
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) bc = DirichletBC(V.sub(0), bc0, lambda x, on_boundary: on_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, b = assemble_system(a, L, 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 automated_fenics_assembly(): mesh = UnitSquareMesh(5, 5) mesh.init() A, b = myassemble(mesh) f = Constant(1) V = FunctionSpace(mesh, 'CG', 1) u = TrialFunction(V) v = TestFunction(V) a = inner(grad(u), grad(v)) * dx L = f * v * dx A1, b1 = assemble_system(a, L) B = A - A1.array() print("The norm of B is {}".format(np.linalg.norm(B))) print("A = ") print(A) print("A1 = ") print(A1.array())
def project(v, V=None, bcs=None, mesh=None, function=None, solver_type="lu", preconditioner_type="default", form_compiler_parameters=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>`. solver_type see :py:func:`solve <dolfin.fem.solving.solve>` for options. preconditioner_type see :py:func:`solve <dolfin.fem.solving.solve>` for options. form_compiler_parameters see :py:class:`Parameters <dolfin.cpp.Parameters>` for more information. *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, dolfin.function.expression.Expression): if mesh is not None and isinstance(mesh, cpp.mesh.Mesh): V = 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) # Projection into a MultiMeshFunctionSpace if isinstance(V, MultiMeshFunctionSpace): # Create the measuresum of uncut and cut-cells dX = ufl.dx() + ufl.dC() # Define variational problem for projection w = TestFunction(V) Pv = TrialFunction(V) a = ufl.inner(w, Pv) * dX L = ufl.inner(w, v) * dX # Assemble linear system A = assemble_multimesh(a, form_compiler_parameters=form_compiler_parameters) b = assemble_multimesh(L, form_compiler_parameters=form_compiler_parameters) # Solve linear system for projection if function is None: function = MultiMeshFunction(V) cpp.la.solve(A, function.vector(), b, solver_type, preconditioner_type) return function # 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 = TestFunction(V) Pv = TrialFunction(V) a = ufl.inner(w, Pv) * dx L = ufl.inner(w, v) * dx # Assemble linear system A, b = assemble_system(a, L, bcs=bcs, form_compiler_parameters=form_compiler_parameters) # Solve linear system for projection if function is None: function = Function(V) cpp.la.solve(A, function.vector(), b, solver_type, preconditioner_type) return function
def xtest_mg_solver_stokes(): mesh0 = UnitCubeMesh(2, 2, 2) mesh1 = UnitCubeMesh(4, 4, 4) mesh2 = UnitCubeMesh(8, 8, 8) Ve = VectorElement("CG", mesh0.ufl_cell(), 2) Qe = FiniteElement("CG", mesh0.ufl_cell(), 1) Ze = MixedElement([Ve, Qe]) Z0 = FunctionSpace(mesh0, Ze) Z1 = FunctionSpace(mesh1, Ze) Z2 = FunctionSpace(mesh2, Ze) W = Z2 # Boundaries def right(x, on_boundary): return x[0] > (1.0 - DOLFIN_EPS) def left(x, on_boundary): return x[0] < DOLFIN_EPS def top_bottom(x, on_boundary): return x[1] > 1.0 - DOLFIN_EPS or x[1] < DOLFIN_EPS # No-slip boundary condition for velocity noslip = Constant((0.0, 0.0, 0.0)) bc0 = DirichletBC(W.sub(0), noslip, top_bottom) # Inflow boundary condition for velocity inflow = Expression(("-sin(x[1]*pi)", "0.0", "0.0"), degree=2) bc1 = DirichletBC(W.sub(0), inflow, right) # Collect boundary conditions bcs = [bc0, bc1] # Define variational problem (u, p) = TrialFunctions(W) (v, q) = TestFunctions(W) f = Constant((0.0, 0.0, 0.0)) a = inner(grad(u), grad(v)) * dx + div(v) * p * dx + q * div(u) * dx L = inner(f, v) * dx # Form for use in constructing preconditioner matrix b = inner(grad(u), grad(v)) * dx + p * q * dx # Assemble system A, bb = assemble_system(a, L, bcs) # Assemble preconditioner system P, btmp = assemble_system(b, L, bcs) spaces = [Z0, Z1, Z2] dm_collection = PETScDMCollection(spaces) solver = PETScKrylovSolver() solver.set_operators(A, P) PETScOptions.set("ksp_type", "gcr") PETScOptions.set("pc_type", "mg") PETScOptions.set("pc_mg_levels", 3) PETScOptions.set("pc_mg_galerkin") PETScOptions.set("ksp_monitor_true_residual") PETScOptions.set("ksp_atol", 1.0e-10) PETScOptions.set("ksp_rtol", 1.0e-10) solver.set_from_options() from petsc4py import PETSc ksp = solver.ksp() ksp.setDM(dm_collection.dm()) ksp.setDMActive(False) x = PETScVector() solver.solve(x, bb) # Check multigrid solution against LU solver solver = LUSolver(A) # noqa x_lu = PETScVector() solver.solve(x_lu, bb) assert round((x - x_lu).norm("l2"), 10) == 0 # Clear all PETSc options opts = PETSc.Options() for key in opts.getAll(): opts.delValue(key)
# Create function space V = VectorFunctionSpace(mesh, "Lagrange", 1) # Define variational problem u = TrialFunction(V) v = TestFunction(V) a = inner(sigma(u), grad(v)) * dx L = inner(f, v) * dx # Set up boundary condition on inner surface c = Constant((0.0, 0.0, 0.0)) bc = DirichletBC(V, c, boundary) # Assemble system, applying boundary conditions and preserving # symmetry) A, b = assemble_system(a, L, bc) # Create solution function u = Function(V) # Create near null space basis (required for smoothed aggregation # AMG). The solution vector is passed so that it can be copied to # generate compatible vectors for the nullspace. null_space = build_nullspace(V, u.vector()) # Attach near nullspace to matrix A.set_near_nullspace(null_space) # Set solver options PETScOptions.set("ksp_view") PETScOptions.set("ksp_type", "cg")