コード例 #1
0
 def __init__(self, block_form, block_function_space, form_compiler_parameters=None):
     # Store UFL form
     self._block_form = block_form
     # Store block function space
     assert len(block_function_space) == 2
     self._block_function_space = block_function_space
     # Replace UFL form by Dolfin form before passing it to the constructor
     # (note that we assume that block_form has been already preprocessed,
     #  so we can assume that nested blocks have been unrolled and zero
     #  placeholders have been replaced by zero forms)
     N = len(block_form)
     M = len(block_form[0])
     assert all([len(block_form_I) == M for block_form_I in block_form])
     replaced_block_form = empty((N, M), dtype=object)
     for I in range(N):
         for J in range(M):
             if isinstance(block_form[I, J], Form) and has_exact_type(block_form[I, J], CoefficientDerivative):
                 block_form[I, J] = expand_derivatives(block_form[I, J])
             replaced_block_form[I, J] = block_replace_zero(block_form, (I, J), block_function_space)
             assert isinstance(replaced_block_form[I, J], Form) or _is_zero(replaced_block_form[I, J])
             if isinstance(replaced_block_form[I, J], Form):
                 replaced_block_form[I, J] = _create_dolfin_form(
                     form=replaced_block_form[I, J],
                     form_compiler_parameters=form_compiler_parameters
                 )
             elif _is_zero(replaced_block_form[I, J]):
                 assert isinstance(replaced_block_form[I, J], cpp_Form)
             else:
                 raise TypeError("Invalid form")
     BlockForm2_Base.__init__(self, replaced_block_form.tolist(), [block_function_space_.cpp_object() for block_function_space_ in block_function_space])
     # Store sizes for shape method
     self.N = N
     self.M = M
コード例 #2
0
 def __init__(self, block_form, block_function_space, form_compiler_parameters=None):
     # Store UFL form
     self._block_form = block_form
     # Store block function space
     assert len(block_function_space) == 1
     self._block_function_space = block_function_space
     # Replace UFL form by Dolfin form before passing it to the constructor
     # (note that we assume that block_form has been already preprocessed,
     #  so we can assume that nested blocks have been unrolled and zero
     #  placeholders have been replaced by zero forms)
     N = len(block_form)
     replaced_block_form = empty((N, ), dtype=object)
     for I in range(N):
         replaced_block_form[I] = block_replace_zero(block_form, (I, ), block_function_space)
         assert isinstance(replaced_block_form[I], Form) or _is_zero(replaced_block_form[I])
         if isinstance(replaced_block_form[I], Form):
             replaced_block_form[I] = _create_dolfin_form(
                 form=replaced_block_form[I],
                 form_compiler_parameters=form_compiler_parameters
             )
         elif _is_zero(replaced_block_form[I]):
             assert isinstance(replaced_block_form[I], cpp_Form)
         else:
             raise TypeError("Invalid form")
     BlockForm1_Base.__init__(self, replaced_block_form.tolist(), [block_function_space_.cpp_object() for block_function_space_ in block_function_space])
     # Store size for len and shape method
     self.N = N
コード例 #3
0
def block_adjoint(block_form):
    assert isinstance(block_form, (array, list, BlockForm2))
    if isinstance(block_form, (array, list)):
        input_type = array
        (block_form, block_function_space, block_form_rank) = _block_form_preprocessing(block_form)
        assert block_form_rank == 2
        N = len(block_form)
        M = len(block_form[0])
        block_adjoint_function_space = [block_function_space[1], block_function_space[0]]
    else:
        input_type = BlockForm2
        N = block_form.block_size(0)
        M = block_form.block_size(1)
        block_adjoint_function_space = [block_form.block_function_spaces(1), block_form.block_function_spaces(0)]
    block_test_function_adjoint = BlockTestFunction(block_adjoint_function_space[0])
    block_trial_function_adjoint = BlockTrialFunction(block_adjoint_function_space[1])
    block_adjoint_form = empty((M, N), dtype=object)
    for I in range(N):
        for J in range(M):
            assert isinstance(block_form[I, J], Form) or _is_zero(block_form[I, J])
            if isinstance(block_form[I, J], Form):
                block_adjoint_form[J, I] = adjoint(block_form[I, J], (block_test_function_adjoint[J], block_trial_function_adjoint[I]))
            elif _is_zero(block_form[I, J]):
                block_adjoint_form[J, I] = 0
            else:
                raise TypeError("Invalid form")
    if input_type is array:
        return block_adjoint_form
    elif input_type is BlockForm2:
        return BlockForm2(block_adjoint_form, block_function_space=block_adjoint_function_space)
コード例 #4
0
def _block_form_preprocessing(block_form,
                              block_function_space=None,
                              block_form_rank=None):
    assert isinstance(block_form, (array, list))
    if block_form_rank is None:
        block_form_rank = _get_block_form_rank(block_form)
        assert block_form_rank is not None, \
            "A block form rank should be provided when assemblying a zero block vector/matrix."
    assert block_form_rank in (1, 2)
    if block_form_rank == 2:
        # Extract BlockFunctionSpace from the current form, if required
        if not block_function_space:
            assert not all([_is_zero(block_form_I_J) for block_form_I in block_form for block_form_I_J in block_form_I]), \
                "A BlockFunctionSpace should be provided when assemblying a zero block matrix."
            block_function_space = _extract_block_function_space_2(block_form)
            assert len(block_function_space) == 2
            assert block_function_space[0] is not None
            assert block_function_space[1] is not None
            block_function_space = [
                block_function_space[0], block_function_space[1]
            ]  # convert from dict to list
        else:
            assert isinstance(block_function_space, list)
            assert len(block_function_space) == 2
            assert isinstance(block_function_space[0], BlockFunctionSpace)
            assert isinstance(block_function_space[1], BlockFunctionSpace)

        # Flatten nested blocks, if any
        block_form = block_flatten_nested(block_form, block_function_space)

        # Return preprocessed data
        return (block_form, block_function_space, block_form_rank)
    elif block_form_rank == 1:
        # Extract BlockFunctionSpace from the current form, if required
        if not block_function_space:
            assert not all([_is_zero(block_form_I) for block_form_I in block_form]), \
                "A BlockFunctionSpace should be provided when assemblying a zero block vector."
            block_function_space = _extract_block_function_space_1(block_form)
            assert len(block_function_space) == 1
            assert block_function_space[0] is not None
            block_function_space = [block_function_space[0]
                                    ]  # convert from dict to list
        else:
            assert isinstance(block_function_space, BlockFunctionSpace)
            block_function_space = [block_function_space]

        # Flatten nested blocks, if any
        block_form = block_flatten_nested(block_form, block_function_space)

        # Return preprocessed data
        return (block_form, block_function_space, block_form_rank)
コード例 #5
0
 def __rmul__(self, other):
     if isinstance(other, float):
         output_block_form = empty((self.N, ), dtype=object)
         for I in range(self.N):
             assert isinstance(self[I], Form) or _is_zero(self[I])
             if isinstance(self[I], Form):
                 output_block_form[I] = other*self[I]
             elif _is_zero(self[I]):
                 output_block_form[I] = 0
             else:
                 raise TypeError("Invalid form")
         return BlockForm1(output_block_form, self._block_function_space)
     else:
         return NotImplemented
コード例 #6
0
def _extract_block_function_space_1(block_form):
    block_function_space = dict()

    for block_form_I in block_form:
        if _is_zero(block_form_I):
            continue
        elif isinstance(block_form_I, (array, list)):
            if isinstance(block_form_I[0], list) or isinstance(
                    block_form_I[0], array):
                block_function_space_recursive = _extract_block_function_space_2(
                    block_form_I)
            else:
                block_function_space_recursive = _extract_block_function_space_1(
                    block_form_I)
            for (number, block_function_space_number
                 ) in block_function_space_recursive.items():
                if number in block_function_space:
                    assert block_function_space[
                        number] == block_function_space_number
                else:
                    block_function_space[number] = block_function_space_number
        else:
            assert isinstance(block_form_I, Form)
            for (index, arg) in enumerate(block_form_I.arguments()):
                number = arg.number()
                block_function_space_arg = arg.block_function_space()
                if number in block_function_space:
                    assert block_function_space[
                        number] == block_function_space_arg
                else:
                    block_function_space[number] = block_function_space_arg

    return block_function_space
コード例 #7
0
def block_derivative(F, u, du):
    assert isinstance(F, (array, list, BlockForm1))
    if isinstance(F, (array, list)):
        input_type = array
        (F, block_V, block_form_rank) = _block_form_preprocessing(F)
        assert block_form_rank == 1
    else:
        input_type = BlockForm1
        block_V = F.block_function_spaces()
    assert len(block_V) == 1
    block_V = block_V[0]
    
    # Compute the derivative
    assert len(F) == len(u) == len(du)
    J = empty((len(F), len(u)), dtype=object)
    for i in range(len(F)):
        if not _is_zero(F[i]):
            for j in range(len(u)):
                J[i, j] = derivative(F[i], u[j], du[j])
        else:
            J[i, :] = 0
    if input_type is array:
        return J
    elif input_type is BlockForm1:
        return BlockForm2(J, block_function_space=[du.block_function_space(), block_V])
コード例 #8
0
def _flatten_nested_1(form_or_block_form, flattened_block_form, block_function_space):
    is_zero = _is_zero(form_or_block_form)
    assert is_zero or isinstance(form_or_block_form, (array, Form, list))
    if is_zero:
        pass
    elif isinstance(form_or_block_form, Form):
        args = _extract_arguments(form_or_block_form)
        test_block_index = None
        test_block_function_space = None
        for arg in args:
            assert arg.number() == 0
            if test_block_index is not None:
                assert test_block_index == arg.block_index(), "Test functions corresponding to different blocks appear in the same form."
                assert test_block_function_space == arg.block_function_space(), "Test functions defined in different block function spaces appear in the same form."
            else:
                test_block_index = arg.block_index()
                test_block_function_space = arg.block_function_space()
        assert test_block_index is not None
        assert test_block_function_space is not None
        if hasattr(block_function_space[0], "is_block_subspace"):
            assert test_block_index in block_function_space[0].components_to_sub_components, "Block function space and test block index are not consistent on the sub space."
            test_block_index = block_function_space[0].components_to_sub_components[test_block_index]
            assert test_block_function_space == block_function_space[0].parent_block_function_space
        else:
            assert test_block_function_space == block_function_space[0]
        flattened_block_form[test_block_index] += form_or_block_form
    elif isinstance(form_or_block_form, (array, list)):
        assert _get_block_form_rank(form_or_block_form) == 1
        for block_form_I_nested in form_or_block_form:
            _flatten_nested_1(block_form_I_nested, flattened_block_form, block_function_space)
    else:
        raise AssertionError("Invalid case in _flatten_nested_1")
コード例 #9
0
def _create_block_tensor(comm, block_form, rank, block_tensor):
    backend = BlockDefaultFactory()
    block_tensor = _dolfin_create_tensor(comm, block_form, rank, backend, block_tensor)
    block_tensor = as_backend_type(block_tensor)

    # Attach block dofmap to tensor
    assert rank in (1, 2)
    if rank == 2:
        block_dofmap_0 = block_form.block_function_spaces()[0].block_dofmap()
        block_dofmap_1 = block_form.block_function_spaces()[1].block_dofmap()
        assert block_tensor.has_block_dof_map(0) == block_tensor.has_block_dof_map(1)
        if not block_tensor.has_block_dof_map(0):
            block_tensor.attach_block_dof_map(block_dofmap_0, block_dofmap_1)
        else:
            assert block_dofmap_0 == block_tensor.get_block_dof_map(0)
            assert block_dofmap_1 == block_tensor.get_block_dof_map(1)
    elif rank == 1:
        block_dofmap = block_form.block_function_spaces()[0].block_dofmap()
        if not block_tensor.has_block_dof_map():
            block_tensor.attach_block_dof_map(block_dofmap)
        else:
            assert block_dofmap == block_tensor.get_block_dof_map()

    # Store private attribute for BlockDirichletBC application to off diagonal blocks
    if rank == 2:
        bcs_zero_off_block_diagonal = empty(block_form.shape, dtype=bool)
        for I in range(block_form.shape[0]):
            for J in range(block_form.shape[1]):
                bcs_zero_off_block_diagonal[I, J] = not _is_zero(block_form[I, J])
        block_tensor._bcs_zero_off_block_diagonal = bcs_zero_off_block_diagonal.tolist()

    return block_tensor
コード例 #10
0
 def __add__(self, other):
     if isinstance(other, BlockForm2):
         assert self.N == other.N
         assert self.M == other.M
         assert self._block_function_space[
             0] is other._block_function_space[0]
         assert self._block_function_space[
             1] is other._block_function_space[1]
         output_block_form = empty((self.N, self.M), dtype=object)
         for I in range(self.N):
             for J in range(self.M):
                 assert isinstance(self[I, J], Form) or _is_zero(self[I, J])
                 assert isinstance(other[I, J], Form) or _is_zero(other[I,
                                                                        J])
                 if (isinstance(self[I, J], Form)
                         and isinstance(other[I, J], Form)):
                     output_block_form[I, J] = self[I, J] + other[I, J]
                 elif (isinstance(self[I, J], Form)
                       and _is_zero(other[I, J])):
                     output_block_form[I, J] = self[I, J]
                 elif (isinstance(other[I, J], Form)
                       and _is_zero(self[I, J])):
                     output_block_form[I, J] = other[I, J]
                 elif (_is_zero(self[I, J]) and _is_zero(other[I, J])):
                     output_block_form[I, J] = 0
                 else:
                     raise TypeError("Invalid form")
         return BlockForm2(output_block_form, self._block_function_space)
     else:
         return NotImplemented
コード例 #11
0
def _block_form_preprocessing(block_form,
                              block_function_space=None,
                              block_form_rank=None):
    assert isinstance(block_form, (array, list))
    if block_form_rank is None:
        block_form_rank = _get_block_form_rank(block_form)
        assert block_form_rank is not None, \
            "A block form rank should be provided when assemblying a zero block vector/matrix."
    assert block_form_rank in (1, 2)
    if block_form_rank is 2:
        # Extract BlockFunctionSpace from the current form, if required
        if not block_function_space:
            assert not all([_is_zero(block_form_I_J) for block_form_I in block_form for block_form_I_J in block_form_I]), \
                "A BlockFunctionSpace should be provided when assemblying a zero block matrix."
            block_function_space = _extract_block_function_space_2(block_form)
            assert len(block_function_space) == 2
            assert block_function_space[0] is not None
            assert block_function_space[1] is not None
            block_function_space = [
                block_function_space[0], block_function_space[1]
            ]  # convert from dict to list
        else:
            assert isinstance(block_function_space, list)
            assert len(block_function_space) is 2
            assert isinstance(block_function_space[0], BlockFunctionSpace)
            assert isinstance(block_function_space[1], BlockFunctionSpace)

        # Flatten nested blocks, if any
        block_form = block_flatten_nested(block_form, block_function_space)
        # ... and compute size accordingly
        if block_function_space[0] == block_function_space[1]:
            _assert_flattened_form_2_is_square(block_form)
        N = len(block_form)
        M = len(block_form[0])

        # Replace zero blocks, if any
        replaced_block_form = empty((N, M), dtype=object)
        for I in range(N):
            for J in range(M):
                replaced_block_form[I, J] = block_replace_zero(
                    block_form, (I, J), block_function_space)

        # Return preprocessed data
        return (replaced_block_form, block_function_space, block_form_rank)
    elif block_form_rank is 1:
        # Extract BlockFunctionSpace from the current form, if required
        if not block_function_space:
            assert not all([_is_zero(block_form_I) for block_form_I in block_form]), \
                "A BlockFunctionSpace should be provided when assemblying a zero block vector."
            block_function_space = _extract_block_function_space_1(block_form)
            assert len(block_function_space) == 1
            assert block_function_space[0] is not None
            block_function_space = [block_function_space[0]
                                    ]  # convert from dict to list
        else:
            assert isinstance(block_function_space, BlockFunctionSpace)
            block_function_space = [block_function_space]

        # Flatten nested blocks, if any
        block_form = block_flatten_nested(block_form, block_function_space)
        # ... and compute size accordingly
        N = len(block_form)

        # Replace zero blocks, if any
        replaced_block_form = empty((N, ), dtype=object)
        for I in range(N):
            replaced_block_form[I] = block_replace_zero(
                block_form, (I, ), block_function_space)

        # Return preprocessed data
        return (replaced_block_form, block_function_space, block_form_rank)