Exemplo n.º 1
0
def assemble_system(A_form,
                    b_form,
                    bcs=None,
                    x0=None,
                    A_coefficients=None,
                    b_coefficients=None,
                    A_function_spaces=None,
                    b_function_spaces=None,
                    cell_domains=None,
                    exterior_facet_domains=None,
                    interior_facet_domains=None,
                    reset_sparsity=True,
                    add_values=False,
                    finalize_tensor=True,
                    keep_diagonal=False,
                    A_tensor=None,
                    b_tensor=None,
                    backend=None,
                    form_compiler_parameters=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>`.

    """

    # Extract subdomains
    subdomains = {
        "cell": cell_domains,
        "exterior_facet": exterior_facet_domains,
        "interior_facet": interior_facet_domains
    }

    # Wrap forms
    A_dolfin_form = Form(A_form, A_function_spaces, A_coefficients, subdomains,
                         form_compiler_parameters)
    b_dolfin_form = Form(b_form, b_function_spaces, b_coefficients, subdomains,
                         form_compiler_parameters)

    # Create tensors
    A_tensor = _create_tensor(A_form, A_dolfin_form.rank(), backend, A_tensor)
    b_tensor = _create_tensor(b_form, b_dolfin_form.rank(), backend, b_tensor)

    # Extract domains
    cell_domains, exterior_facet_domains, interior_facet_domains = \
        _extract_domains(A_dolfin_form.mesh(),
                         cell_domains,
                         exterior_facet_domains,
                         interior_facet_domains)

    # Attach domains to form (from Mesh, in other cases form already
    # has domain data attached)
    if cell_domains is not None:
        A_dolfin_form.set_cell_domains(cell_domains)
        b_dolfin_form.set_cell_domains(cell_domains)
    if interior_facet_domains is not None:
        A_dolfin_form.set_interior_facet_domains(interior_facet_domains)
        b_dolfin_form.set_interior_facet_domains(interior_facet_domains)
    if exterior_facet_domains is not None:
        A_dolfin_form.set_exterior_facet_domains(exterior_facet_domains)
        b_dolfin_form.set_exterior_facet_domains(exterior_facet_domains)

    # Check bcs
    bcs = _wrap_in_list(bcs, 'bcs', cpp.DirichletBC)

    # Call C++ assemble function
    assembler = cpp.SystemAssembler(A_dolfin_form, b_dolfin_form, bcs)
    assembler.reset_sparsity = reset_sparsity
    assembler.add_values = add_values
    assembler.finalize_tensor = finalize_tensor
    assembler.keep_diagonal = keep_diagonal
    if x0 is not None:
        assembler.assemble(A_tensor, b_tensor, x0)
    else:
        assembler.assemble(A_tensor, b_tensor)

    return A_tensor, b_tensor
Exemplo n.º 2
0
def assemble_system(A_form,
                    b_form,
                    bcs=None,
                    x0=None,
                    form_compiler_parameters=None,
                    add_values=False,
                    finalize_tensor=True,
                    keep_diagonal=False,
                    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_dolfin_form(A_form, form_compiler_parameters)
    b_dolfin_form = _create_dolfin_form(b_form, form_compiler_parameters)

    # Create tensors
    A_tensor = _create_tensor(A_form, A_dolfin_form.rank(), backend, A_tensor)
    b_tensor = _create_tensor(b_form, b_dolfin_form.rank(), backend, b_tensor)

    # Check bcs
    bcs = _wrap_in_list(bcs, 'bcs', cpp.DirichletBC)

    # Call C++ assemble function
    assembler = cpp.SystemAssembler(A_dolfin_form, b_dolfin_form, bcs)
    assembler.add_values = add_values
    assembler.finalize_tensor = finalize_tensor
    assembler.keep_diagonal = keep_diagonal
    if x0 is not None:
        assembler.assemble(A_tensor, b_tensor, x0)
    else:
        assembler.assemble(A_tensor, b_tensor)

    return A_tensor, b_tensor