class BlockNonlinearProblem(NonlinearProblem):
    def __init__(self, residual_block_form, block_solution, bcs,
                 jacobian_block_form):
        NonlinearProblem.__init__(self)
        # Store the input arguments
        self.residual_block_form = residual_block_form
        self.jacobian_block_form = jacobian_block_form
        self.block_solution = block_solution
        self.bcs = bcs
        # Create block backend for wrapping
        self.block_backend = BlockDefaultFactory()
        self.block_dof_map = self.block_solution.block_function_space(
        ).block_dofmap()

    def F(self, fenics_residual, _):
        # Update block solution subfunctions based on the third argument, which has already been
        # stored in self.block_solution.block_vector()
        self.block_solution.apply("to subfunctions")
        # Wrap FEniCS residual into a block residual
        block_residual = self.block_backend.wrap_vector(fenics_residual)
        # Assemble the block residual
        block_assemble(self.residual_block_form, block_tensor=block_residual)
        # Apply boundary conditions
        if self.bcs is not None:
            self.bcs.apply(block_residual, self.block_solution.block_vector())

    def J(self, fenics_jacobian, _):
        # No need to update block solution subfunctions, this has already been done in the residual
        # Wrap FEniCS jacobian into a block jacobian
        block_jacobian = self.block_backend.wrap_matrix(fenics_jacobian)
        # Assemble the block jacobian
        block_assemble(self.jacobian_block_form, block_tensor=block_jacobian)
        # Apply boundary conditions
        if self.bcs is not None:
            self.bcs.apply(block_jacobian)
 def __init__(self, residual_block_form, block_solution, bcs,
              jacobian_block_form):
     NonlinearProblem.__init__(self)
     # Store the input arguments
     self.residual_block_form = residual_block_form
     self.jacobian_block_form = jacobian_block_form
     self.block_solution = block_solution
     self.bcs = bcs
     # Create block backend for wrapping
     self.block_backend = BlockDefaultFactory()
     self.block_dof_map = self.block_solution.block_function_space(
     ).block_dofmap()
 def __init__(self, block_solution):
     NonlinearProblem.__init__(self)
     rhs = [F_F_n(v), 0, F_P_n(w), G_n(qP), 0]
     F = np.array(lhs).sum(axis=1) - np.array(rhs)
     J = block_derivative(F, trial, dtrial)
     self.residual_block_form = F
     self.jacobian_block_form = J
     self.block_solution = block_solution
     self.bcs = bcs
     # Create block backend for wrapping
     self.block_backend = BlockDefaultFactory()
     self.block_dof_map = self.block_solution.block_function_space(
     ).block_dofmap()
Ejemplo n.º 4
0
 def __init__(self, residual_form_or_eval, block_solution, bcs,
              jacobian_form_or_eval):
     NonlinearProblem.__init__(self)
     # Store the input arguments
     self.residual_form_or_eval = residual_form_or_eval
     self.jacobian_form_or_eval = jacobian_form_or_eval
     self.block_solution = block_solution
     self.bcs = bcs
     # Create block backend for wrapping
     self.block_backend = BlockDefaultFactory()
     self.block_dof_map = self.block_solution.block_function_space(
     ).block_dofmap()
     # =========== PETScSNESSolver::init() workaround for assembled matrices =========== #
     self._J_assemble_failed_in_init = False
Ejemplo n.º 5
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
Ejemplo n.º 6
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 is 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 is 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()

    return block_tensor
    class BiotNSBlockNonLinearProblem(BlockNonlinearProblem):
        def __init__(self, block_solution):
            NonlinearProblem.__init__(self)
            rhs = [F_F_n(v), 0, F_P_n(w), G_n(qP), 0]
            F = np.array(lhs).sum(axis=1) - np.array(rhs)
            J = block_derivative(F, trial, dtrial)
            self.residual_block_form = F
            self.jacobian_block_form = J
            self.block_solution = block_solution
            self.bcs = bcs
            # Create block backend for wrapping
            self.block_backend = BlockDefaultFactory()
            self.block_dof_map = self.block_solution.block_function_space(
            ).block_dofmap()
            # precompute linear part of jacobian
            # self.precomp_jacobian = block_assemble(J, keep_diagonal=self.bcs is not None)

        def J(self, fenics_jacobian, _):
            # No need to update block solution subfunctions, this has already been done in the residual
            # Wrap FEniCS jacobian into a block jacobian
            block_jacobian = self.block_backend.wrap_matrix(fenics_jacobian)
            # Assemble the block jacobian
            block_assemble(self.jacobian_block_form,
                           block_tensor=block_jacobian,
                           keep_diagonal=self.bcs is not None)
            # Apply boundary conditions
            if self.bcs is not None:
                self.bcs.apply(block_jacobian)
Ejemplo n.º 8
0
class BlockNonlinearProblem(NonlinearProblem):
    def __init__(self, residual_form_or_eval, block_solution, bcs,
                 jacobian_form_or_eval):
        NonlinearProblem.__init__(self)
        # Store the input arguments
        self.residual_form_or_eval = residual_form_or_eval
        self.jacobian_form_or_eval = jacobian_form_or_eval
        self.block_solution = block_solution
        self.bcs = bcs
        # Create block backend for wrapping
        self.block_backend = BlockDefaultFactory()
        self.block_dof_map = self.block_solution.block_function_space(
        ).block_dofmap()
        # =========== PETScSNESSolver::init() workaround for assembled matrices =========== #
        self._J_assemble_failed_in_init = False
        # === end === PETScSNESSolver::init() workaround for assembled matrices === end === #

    def F(self, fenics_residual, _):
        # Update block solution subfunctions based on the third argument, which has already been
        # updated in self.block_solution.block_vector()
        self.block_solution.apply("to subfunctions")
        # Wrap FEniCS residual into a block residual
        block_residual = self.block_backend.wrap_vector(fenics_residual)
        # Assemble the block residual
        self._block_residual_vector_assemble(block_residual,
                                             self.block_solution)
        # Apply boundary conditions
        if self.bcs is not None:
            self.bcs.apply(block_residual, self.block_solution.block_vector())

    def _block_residual_vector_assemble(self, block_residual, block_solution):
        assert isinstance(
            self.residual_form_or_eval,
            (list, array, BlockForm1, types.FunctionType, types.MethodType))
        if isinstance(self.residual_form_or_eval, (list, array, BlockForm1)):
            residual_form_or_vector = self.residual_form_or_eval
        elif isinstance(self.residual_form_or_eval,
                        (types.FunctionType, types.MethodType)):
            residual_form_or_vector = self.residual_form_or_eval(
                block_solution)
        else:
            raise AssertionError(
                "Invalid case in BlockNonlinearProblem._block_residual_vector_assemble."
            )
        assert isinstance(residual_form_or_vector,
                          (list, array, BlockForm1, GenericBlockVector))
        if isinstance(residual_form_or_vector, (list, array, BlockForm1)):
            block_assemble(residual_form_or_vector,
                           block_tensor=block_residual)
        elif isinstance(residual_form_or_vector, GenericBlockVector):
            residual_form_or_vector = as_backend_type(residual_form_or_vector)
            block_residual = as_backend_type(block_residual)
            residual_form_or_vector.vec().swap(block_residual.vec())
            assert residual_form_or_vector.has_block_dof_map()
            block_dofmap = residual_form_or_vector.get_block_dof_map()
            if not block_residual.has_block_dof_map():
                block_residual.attach_block_dof_map(block_dofmap)
            else:
                assert block_dofmap == block_residual.get_block_dof_map()
        else:
            raise AssertionError(
                "Invalid case in BlockNonlinearProblem._block_residual_vector_assemble."
            )

    def J(self, fenics_jacobian, _):
        # No need to update block solution subfunctions, this has already been done in the residual
        # Wrap FEniCS jacobian into a block jacobian
        block_jacobian = self.block_backend.wrap_matrix(fenics_jacobian)
        # Assemble the block jacobian
        assembled = self._block_jacobian_matrix_assemble(
            block_jacobian, self.block_solution)
        # =========== PETScSNESSolver::init() workaround for assembled matrices =========== #
        if not assembled:
            assert not self._J_assemble_failed_in_init  # This should happen only once
            self._J_assemble_failed_in_init = True
            return
        # === end === PETScSNESSolver::init() workaround for assembled matrices === end === #
        # Apply boundary conditions
        if self.bcs is not None:
            self.bcs.apply(block_jacobian)

    def _block_jacobian_matrix_assemble(self, block_jacobian, block_solution):
        assert isinstance(
            self.jacobian_form_or_eval,
            (list, array, BlockForm2, types.FunctionType, types.MethodType))
        if isinstance(self.jacobian_form_or_eval, (list, array, BlockForm2)):
            jacobian_form_or_matrix = self.jacobian_form_or_eval
        elif isinstance(self.jacobian_form_or_eval,
                        (types.FunctionType, types.MethodType)):
            jacobian_form_or_matrix = self.jacobian_form_or_eval(
                block_solution)
        else:
            raise AssertionError(
                "Invalid case in BlockNonlinearProblem._block_jacobian_matrix_assemble."
            )
        assert isinstance(jacobian_form_or_matrix,
                          (list, array, BlockForm2, GenericBlockMatrix))
        if isinstance(jacobian_form_or_matrix, (list, array, BlockForm2)):
            block_assemble(jacobian_form_or_matrix,
                           block_tensor=block_jacobian)
            return True
        elif isinstance(jacobian_form_or_matrix, GenericBlockMatrix):
            # =========== PETScSNESSolver::init() workaround for assembled matrices =========== #
            if block_jacobian.empty():
                return False
            # === end === PETScSNESSolver::init() workaround for assembled matrices === end === #
            else:
                jacobian_form_or_matrix = as_backend_type(
                    jacobian_form_or_matrix)
                block_jacobian = as_backend_type(block_jacobian)
                block_jacobian.zero()
                block_jacobian += jacobian_form_or_matrix
                assert jacobian_form_or_matrix.has_block_dof_map(0)
                assert jacobian_form_or_matrix.has_block_dof_map(1)
                block_dofmap_0 = jacobian_form_or_matrix.get_block_dof_map(0)
                block_dofmap_1 = jacobian_form_or_matrix.get_block_dof_map(0)
                assert block_jacobian.has_block_dof_map(
                    0) == block_jacobian.has_block_dof_map(1)
                if not block_jacobian.has_block_dof_map(0):
                    block_jacobian.attach_block_dof_map(
                        block_dofmap_0, block_dofmap_1)
                else:
                    assert block_dofmap_0 == block_jacobian.get_block_dof_map(
                        0)
                    assert block_dofmap_1 == block_jacobian.get_block_dof_map(
                        1)
                return True
        else:
            raise AssertionError(
                "Invalid case in BlockNonlinearProblem._block_jacobian_matrix_assemble."
            )