def solve(*args, **kwargs): """Solve linear system Ax = b or variational problem a == L or F == 0. The DOLFIN solve() function can be used to solve either linear systems or variational problems. The following list explains the various ways in which the solve() function can be used. *1. Solving linear systems* A linear system Ax = b may be solved by calling solve(A, x, b), where A is a matrix and x and b are vectors. Optional arguments may be passed to specify the solver method and preconditioner. Some examples are given below: .. code-block:: python solve(A, x, b) solve(A, x, b, "lu") solve(A, x, b, "gmres", "ilu") solve(A, x, b, "cg", "hypre_amg") Possible values for the solver method and preconditioner depend on which linear algebra backend is used and how that has been configured. To list all available LU methods, run the following command: .. code-block:: python list_lu_methods() To list all available Krylov methods, run the following command: .. code-block:: python list_krylov_methods() To list all available preconditioners, run the following command: .. code-block:: python list_preconditioners() To list all available solver methods, including LU methods, Krylov methods and, possibly, other methods, run the following command: .. code-block:: python list_solver_methods() *2. Solving linear variational problems* A linear variational problem a(u, v) = L(v) for all v may be solved by calling solve(a == L, u, ...), where a is a bilinear form, L is a linear form, u is a Function (the solution). Optional arguments may be supplied to specify boundary conditions or solver parameters. Some examples are given below: .. code-block:: python solve(a == L, u) solve(a == L, u, bcs=bc) solve(a == L, u, bcs=[bc1, bc2]) solve(a == L, u, bcs=bcs, solver_parameters={"linear_solver": "lu"}, form_compiler_parameters={"optimize": True}) For available choices for the 'solver_parameters' kwarg, look at: .. code-block:: python info(LinearVariationalSolver.default_parameters(), 1) *3. Solving nonlinear variational problems* A nonlinear variational problem F(u; v) = 0 for all v may be solved by calling solve(F == 0, u, ...), where the residual F is a linear form (linear in the test function v but possibly nonlinear in the unknown u) and u is a Function (the solution). Optional arguments may be supplied to specify boundary conditions, the Jacobian form or solver parameters. If the Jacobian is not supplied, it will be computed by automatic differentiation of the residual form. Some examples are given below: .. code-block:: python solve(F == 0, u) solve(F == 0, u, bcs=bc) solve(F == 0, u, bcs=[bc1, bc2]) solve(F == 0, u, bcs, J=J, solver_parameters={"linear_solver": "lu"}, form_compiler_parameters={"optimize": True}) For available choices for the 'solver_parameters' kwarg, look at: .. code-block:: python info(NonlinearVariationalSolver.default_parameters(), 1) *4. Solving linear/nonlinear variational problems adaptively Linear and nonlinear variational problems maybe solved adaptively, with automated goal-oriented error control. The automated error control algorithm is based on adaptive mesh refinement in combination with automated generation of dual-weighted residual-based error estimates and error indicators. An adaptive solve may be invoked by giving two additional arguments to the solve call, a numerical error tolerance and a goal functional (a Form). .. code-block:: python M = u*dx() tol = 1.e-6 # Linear variational problem solve(a == L, u, bcs=bc, tol=tol, M=M) # Nonlinear problem: solve(F == 0, u, bcs=bc, tol=tol, M=M) """ assert(len(args) > 0) # Call adaptive solve if we get a tolerance if "tol" in kwargs: _solve_varproblem_adaptive(*args, **kwargs) # Call variational problem solver if we get an equation (but not a tolerance) elif isinstance(args[0], ufl.classes.Equation): _solve_varproblem(*args, **kwargs) # Default case, just call the wrapped C++ solve function else: if kwargs: cpp.dolfin_error("solving.py", "solve linear algebra problem", "Not expecting keyword arguments when solving "\ "linear algebra problem") return cpp.la_solve(*args)
def solve(*args, **kwargs): """Solve linear system Ax = b or variational problem a == L or F == 0. The DOLFIN solve() function can be used to solve either linear systems or variational problems. The following list explains the various ways in which the solve() function can be used. *1. Solving linear systems* A linear system Ax = b may be solved by calling solve(A, x, b), where A is a matrix and x and b are vectors. Optional arguments may be passed to specify the solver method and preconditioner. Some examples are given below: .. code-block:: python solve(A, x, b) solve(A, x, b, "lu") solve(A, x, b, "gmres", "ilu") solve(A, x, b, "cg", "hypre_amg") Possible values for the solver method and preconditioner depend on which linear algebra backend is used and how that has been configured. To list all available LU methods, run the following command: .. code-block:: python list_lu_solver_methods() To list all available Krylov methods, run the following command: .. code-block:: python list_krylov_solver_methods() To list all available preconditioners, run the following command: .. code-block:: python list_krylov_solver_preconditioners() To list all available solver methods, including LU methods, Krylov methods and, possibly, other methods, run the following command: .. code-block:: python list_linear_solver_methods() *2. Solving linear variational problems* A linear variational problem a(u, v) = L(v) for all v may be solved by calling solve(a == L, u, ...), where a is a bilinear form, L is a linear form, u is a Function (the solution). Optional arguments may be supplied to specify boundary conditions or solver parameters. Some examples are given below: .. code-block:: python solve(a == L, u) solve(a == L, u, bcs=bc) solve(a == L, u, bcs=[bc1, bc2]) solve(a == L, u, bcs=bcs, solver_parameters={"linear_solver": "lu"}, form_compiler_parameters={"optimize": True}) For available choices for the 'solver_parameters' kwarg, look at: .. code-block:: python info(LinearVariationalSolver.default_parameters(), True) *3. Solving nonlinear variational problems* A nonlinear variational problem F(u; v) = 0 for all v may be solved by calling solve(F == 0, u, ...), where the residual F is a linear form (linear in the test function v but possibly nonlinear in the unknown u) and u is a Function (the solution). Optional arguments may be supplied to specify boundary conditions, the Jacobian form or solver parameters. If the Jacobian is not supplied, it will be computed by automatic differentiation of the residual form. Some examples are given below: .. code-block:: python solve(F == 0, u) solve(F == 0, u, bcs=bc) solve(F == 0, u, bcs=[bc1, bc2]) solve(F == 0, u, bcs, J=J, solver_parameters={"linear_solver": "lu"}, form_compiler_parameters={"optimize": True}) For available choices for the 'solver_parameters' kwarg, look at: .. code-block:: python info(NonlinearVariationalSolver.default_parameters(), True) *4. Solving linear/nonlinear variational problems adaptively Linear and nonlinear variational problems maybe solved adaptively, with automated goal-oriented error control. The automated error control algorithm is based on adaptive mesh refinement in combination with automated generation of dual-weighted residual-based error estimates and error indicators. An adaptive solve may be invoked by giving two additional arguments to the solve call, a numerical error tolerance and a goal functional (a Form). .. code-block:: python M = u*dx() tol = 1.e-6 # Linear variational problem solve(a == L, u, bcs=bc, tol=tol, M=M) # Nonlinear problem: solve(F == 0, u, bcs=bc, tol=tol, M=M) """ assert (len(args) > 0) # Call adaptive solve if we get a tolerance if "tol" in kwargs: _solve_varproblem_adaptive(*args, **kwargs) # Call variational problem solver if we get an equation (but not a # tolerance) elif isinstance(args[0], ufl.classes.Equation): _solve_varproblem(*args, **kwargs) # Default case, just call the wrapped C++ solve function else: if kwargs: cpp.dolfin_error( "solving.py", "solve linear algebra problem", "Not expecting keyword arguments when solving " "linear algebra problem") return cpp.la_solve(*args)
def project(v, V=None, bcs=None, mesh=None, solver_type="cg", 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 BoundaryCondition <dolfin.fem.bcs.BoundaryCondition>` 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). """ # If trying to project an Expression if V is None and isinstance(v, Expression): if mesh is not None and isinstance(mesh, cpp.Mesh): V = FunctionSpaceBase(mesh, v.ufl_element()) else: raise TypeError, "expected a mesh when projecting an Expression" # Try extracting function space if not specified if V is None: V = _extract_function_space(v, mesh) # Check arguments if not isinstance(V, FunctionSpaceBase): cpp.dolfin_error("projection.py", "compute projection", "Illegal function space for projection, not a FunctionSpace: " + str(v)) # Define variational problem for projection w = TestFunction(V) Pv = TrialFunction(V) a = ufl.inner(w, Pv)*ufl.dx() L = ufl.inner(w, v)*ufl.dx() # Assemble linear system A, b = assemble_system(a, L, bcs=bcs, form_compiler_parameters=form_compiler_parameters) # Solve linear system for projection Pv = Function(V) cpp.la_solve(A, Pv.vector(), b, solver_type, preconditioner_type) return Pv
def project(v, V=None, bcs=None, mesh=None, function=None, solver_type="cg", 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, Expression): if mesh is not None and isinstance(mesh, cpp.Mesh): V = FunctionSpaceBase(mesh, v.ufl_element()) else: raise TypeError( "expected a mesh when projecting an Expression") else: # Otherwise try extracting function space from expression V = _extract_function_space(v, mesh) # Check arguments if not isinstance(V, FunctionSpaceBase): cpp.dolfin_error( "projection.py", "compute projection", "Illegal function space for projection, not a FunctionSpace: " + str(v)) # 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 project(v, V=None, D=None, func_degree=None, bcs=None, mesh=None, function=None, solver_type="lu", preconditioner_type="default", form_compiler_parameters=None): """ This function is a modification of FEniCS's built-in project function to adopt the :math:`r^2dr` measure as opposed to the standard Cartesian :math:`dx` one when the :math:`L_2` projection is computed. I have removed the case for a multimesh function space as we don't use it. .. note:: Note the extra argument func_degree: this is used to interpolate the :math:`r^2` Expression to the same degree as used in the definition of the Trial and Test function spaces. .. note:: I am manually implementing this bug fix that is not yet in the current release: <https://bitbucket.org/fenics-project/dolfin/commits/c438724fa5d7f19504d4e0c48695e17b774b2c2d>_ """ # 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, Expression): # FIXME: Add handling of cpp.MultiMesh if mesh is not None and isinstance(mesh, cpp.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) # Check arguments if not isinstance(V, (FunctionSpace)): cpp.dolfin_error( "projection.py", "compute projection", "Illegal function space for projection, not a FunctionSpace: " + str(v)) # 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 # DS: HERE IS WHERE I MODIFY rD = Expression('pow(x[0],D-1)', D=D, degree=func_degree) w = TestFunction(V) Pv = TrialFunction(V) a = ufl.inner(w, Pv) * rD * dx L = ufl.inner(w, v) * rD * 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