Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
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