示例#1
0
    def _forward_solve(self, lhs, rhs, func, bcs, **kwargs):
        solver = self.block_helper.forward_solver
        if solver is None:
            solver = backend.KrylovSolver(self.method, self.preconditioner)
            if self.assemble_system:
                A, _ = backend.assemble_system(lhs, rhs, bcs)
                if self.pc_operator is not None:
                    P = self._replace_form(self.pc_operator)
                    P, _ = backend.assemble_system(P, rhs, bcs)
                    solver.set_operators(A, P)
                else:
                    solver.set_operator(A)
            else:
                A = compat.assemble_adjoint_value(lhs)
                [bc.apply(A) for bc in bcs]
                if self.pc_operator is not None:
                    P = self._replace_form(self.pc_operator)
                    P = compat.assemble_adjoint_value(P)
                    [bc.apply(P) for bc in bcs]
                    solver.set_operators(A, P)
                else:
                    solver.set_operator(A)
            self.block_helper.forward_solver = solver

        if self.assemble_system:
            system_assembler = backend.SystemAssembler(lhs, rhs, bcs)
            b = backend.Function(self.function_space).vector()
            system_assembler.assemble(b)
        else:
            b = compat.assemble_adjoint_value(rhs)
            [bc.apply(b) for bc in bcs]

        solver.parameters.update(self.krylov_solver_parameters)
        solver.solve(func.vector(), b)
        return func
示例#2
0
    def _assemble_and_solve_adj_eq(self, dFdu_adj_form, dJdu, compute_bdy):
        dJdu_copy = dJdu.copy()
        bcs = self._homogenize_bcs()

        solver = self.block_helper.adjoint_solver
        if solver is None:
            solver = backend.PETScKrylovSolver(self.method, self.preconditioner)
            solver.ksp().setOptionsPrefix(self.ksp_options_prefix)
            solver.set_from_options()

            if self.assemble_system:
                rhs_bcs_form = backend.inner(backend.Function(self.function_space),
                                             dFdu_adj_form.arguments()[0]) * backend.dx
                A, _ = backend.assemble_system(dFdu_adj_form, rhs_bcs_form, bcs)

                if self._ad_nullspace is not None:
                    as_backend_type(A).set_nullspace(self._ad_nullspace)

                if self.pc_operator is not None:
                    P = self._replace_form(self.pc_operator)
                    P, _ = backend.assemble_system(P, rhs_bcs_form, bcs)
                    solver.set_operators(A, P)
                else:
                    solver.set_operator(A)
            else:
                A = compat.assemble_adjoint_value(dFdu_adj_form)
                [bc.apply(A) for bc in bcs]

                if self._ad_nullspace is not None:
                    as_backend_type(A).set_nullspace(self._ad_nullspace)

                if self.pc_operator is not None:
                    P = self._replace_form(self.pc_operator)
                    P = compat.assemble_adjoint_value(P)
                    [bc.apply(P) for bc in bcs]
                    solver.set_operators(A, P)
                else:
                    solver.set_operator(A)

            self.block_helper.adjoint_solver = solver

        solver.parameters.update(self.krylov_solver_parameters)
        [bc.apply(dJdu) for bc in bcs]

        if self._ad_nullspace is not None:
            if self._ad_nullspace._ad_orthogonalized:
                self._ad_nullspace.orthogonalize(dJdu)

        adj_sol = backend.Function(self.function_space)
        solver.solve(adj_sol.vector(), dJdu)

        adj_sol_bdy = None
        if compute_bdy:
            adj_sol_bdy = compat.function_from_vector(self.function_space, dJdu_copy - compat.assemble_adjoint_value(
                backend.action(dFdu_adj_form, adj_sol)))

        return adj_sol, adj_sol_bdy
示例#3
0
    def _forward_solve(self, lhs, rhs, func, bcs, **kwargs):
        solver = self.block_helper.forward_solver
        if solver is None:
            solver = backend.PETScKrylovSolver(self.method, self.preconditioner)
            solver.ksp().setOptionsPrefix(self.ksp_options_prefix)
            solver.set_from_options()

            if self.assemble_system:
                A, _ = backend.assemble_system(lhs, rhs, bcs)
                if self._ad_nullspace is not None:
                    as_backend_type(A).set_nullspace(self._ad_nullspace)

                if self.pc_operator is not None:
                    P = self._replace_form(self.pc_operator)
                    P, _ = backend.assemble_system(P, rhs, bcs)
                    solver.set_operators(A, P)
                else:
                    solver.set_operator(A)
            else:
                A = compat.assemble_adjoint_value(lhs)
                [bc.apply(A) for bc in bcs]
                if self._ad_nullspace is not None:
                    as_backend_type(A).set_nullspace(self._ad_nullspace)

                if self.pc_operator is not None:
                    P = self._replace_form(self.pc_operator)
                    P = compat.assemble_adjoint_value(P)
                    [bc.apply(P) for bc in bcs]
                    solver.set_operators(A, P)
                else:
                    solver.set_operator(A)
            self.block_helper.forward_solver = solver

        if self.assemble_system:
            system_assembler = backend.SystemAssembler(lhs, rhs, bcs)
            b = backend.Function(self.function_space).vector()
            system_assembler.assemble(b)
        else:
            b = compat.assemble_adjoint_value(rhs)
            [bc.apply(b) for bc in bcs]

        if self._ad_nullspace is not None:
            if self._ad_nullspace._ad_orthogonalized:
                self._ad_nullspace.orthogonalize(b)

        solver.parameters.update(self.krylov_solver_parameters)
        solver.solve(func.vector(), b)
        return func
示例#4
0
def assemble_system(*args, **kwargs):
    """When a form is assembled, the information about its nonlinear dependencies is lost,
    and it is no longer easy to manipulate. Therefore, fenics_adjoint overloads the :py:func:`dolfin.assemble_system`
    function to *attach the form to the assembled object*. This lets the automatic annotation work,
    even when the user calls the lower-level :py:data:`solve(A, x, b)`.
    """
    A_form = args[0]
    b_form = args[1]

    A, b = backend.assemble_system(*args, **kwargs)

    if "bcs" in kwargs:
        bcs = kwargs["bcs"]
    elif len(args) > 2:
        bcs = args[2]
    else:
        bcs = []

    A.form = A_form
    A.bcs = bcs
    b.form = b_form
    b.bcs = bcs
    A.assemble_system = True

    return A, b
示例#5
0
    def _assemble_and_solve_adj_eq(self, dFdu_adj_form, dJdu, compute_bdy):
        dJdu_copy = dJdu.copy()
        bcs = self._homogenize_bcs()

        solver = self.block_helper.adjoint_solver
        if solver is None:
            if self.assemble_system:
                rhs_bcs_form = backend.inner(
                    backend.Function(self.function_space),
                    dFdu_adj_form.arguments()[0]) * backend.dx
                A, _ = backend.assemble_system(dFdu_adj_form, rhs_bcs_form,
                                               bcs)
            else:
                A = compat.assemble_adjoint_value(dFdu_adj_form)
                [bc.apply(A) for bc in bcs]

            solver = backend.LUSolver(A, self.method)
            self.block_helper.adjoint_solver = solver

        solver.parameters.update(self.lu_solver_parameters)
        [bc.apply(dJdu) for bc in bcs]

        adj_sol = backend.Function(self.function_space)
        solver.solve(adj_sol.vector(), dJdu)

        adj_sol_bdy = None
        if compute_bdy:
            adj_sol_bdy = compat.function_from_vector(
                self.function_space, dJdu_copy - compat.assemble_adjoint_value(
                    backend.action(dFdu_adj_form, adj_sol)))

        return adj_sol, adj_sol_bdy
示例#6
0
    def _assemble_and_solve_adj_eq(self, dFdu_adj_form, dJdu, compute_bdy):
        dJdu_copy = dJdu.copy()
        bcs = self._homogenize_bcs()
        if self.assemble_system:
            rhs_bcs_form = backend.inner(
                backend.Function(self.function_space),
                dFdu_adj_form.arguments()[0]) * backend.dx
            A, _ = backend.assemble_system(dFdu_adj_form, rhs_bcs_form, bcs)
        else:
            A = backend.assemble(dFdu_adj_form)
            [bc.apply(A) for bc in bcs]

        [bc.apply(dJdu) for bc in bcs]

        adj_sol = compat.create_function(self.function_space)
        compat.linalg_solve(A, adj_sol.vector(), dJdu, *self.adj_args,
                            **self.adj_kwargs)

        adj_sol_bdy = None
        if compute_bdy:
            adj_sol_bdy = compat.function_from_vector(
                self.function_space, dJdu_copy - compat.assemble_adjoint_value(
                    backend.action(dFdu_adj_form, adj_sol)))

        return adj_sol, adj_sol_bdy
示例#7
0
    def _forward_solve(self, lhs, rhs, func, bcs, **kwargs):
        if self.assemble_system:
            A, b = backend.assemble_system(lhs, rhs, bcs)
        else:
            A = backend.assemble(lhs)
            b = backend.assemble(rhs)
            [bc.apply(A, b) for bc in bcs]

        if self.ident_zeros_tol is not None:
            A.ident_zeros(self.ident_zeros_tol)

        backend.solve(A, func.vector(), b, *self.forward_args,
                      **self.forward_kwargs)
        return func
示例#8
0
def assemble_system(*args, **kwargs):
    """When a form is assembled, the information about its nonlinear dependencies is lost,
    and it is no longer easy to manipulate. Therefore, dolfin_adjoint overloads the :py:func:`dolfin.assemble_system`
    function to *attach the form to the assembled object*. This lets the automatic annotation work,
    even when the user calls the lower-level :py:data:`solve(A, x, b)`.
    """
    lhs = args[0]
    rhs = args[1]
    caching.assembled_fwd_forms.add(lhs)
    caching.assembled_fwd_forms.add(rhs)

    cache = kwargs.pop("cache", False)

    if 'bcs' in kwargs:
        bcs = kwargs['bcs']
    elif len(args) > 2:
        bcs = args[2]
    else:
        bcs = []

    if not isinstance(bcs, list):
        bcs = [bcs]

    to_annotate = utils.to_annotate(kwargs.pop("annotate", None))

    (lhs_out, rhs_out) = backend.assemble_system(*args, **kwargs)

    if to_annotate:
        lhs_out.form = lhs
        lhs_out.bcs = bcs
        lhs_out.assemble_system = True
        rhs_out.form = rhs
        rhs_out.bcs = bcs
        rhs_out.assemble_system = True

    if cache:
        caching.assembled_adj_forms[lhs] = lhs_out
        caching.assembled_adj_forms[rhs] = rhs_out

    return (lhs_out, rhs_out)
示例#9
0
def assemble_system(*args, **kwargs):
    """When a form is assembled, the information about its nonlinear dependencies is lost,
  and it is no longer easy to manipulate. Therefore, dolfin_adjoint overloads the :py:func:`dolfin.assemble_system`
  function to *attach the form to the assembled object*. This lets the automatic annotation work,
  even when the user calls the lower-level :py:data:`solve(A, x, b)`.
  """
    lhs = args[0]
    rhs = args[1]
    caching.assembled_fwd_forms.add(lhs)
    caching.assembled_fwd_forms.add(rhs)

    cache = kwargs.pop("cache", False)

    if "bcs" in kwargs:
        bcs = kwargs["bcs"]
    elif len(args) > 2:
        bcs = args[2]
    else:
        bcs = []

    if not isinstance(bcs, list):
        bcs = [bcs]

    (lhs_out, rhs_out) = backend.assemble_system(*args, **kwargs)

    to_annotate = utils.to_annotate(kwargs.pop("annotate", None))
    if to_annotate:
        lhs_out.form = lhs
        lhs_out.bcs = bcs
        lhs_out.assemble_system = True
        rhs_out.form = rhs
        rhs_out.bcs = bcs
        rhs_out.assemble_system = True

    if cache:
        caching.assembled_adj_forms[lhs] = lhs_out
        caching.assembled_adj_forms[rhs] = rhs_out

    return (lhs_out, rhs_out)
示例#10
0
    def _forward_solve(self, lhs, rhs, func, bcs, **kwargs):
        solver = self.block_helper.forward_solver
        if solver is None:
            if self.assemble_system:
                A, _ = backend.assemble_system(lhs, rhs, bcs)
            else:
                A = compat.assemble_adjoint_value(lhs)
                [bc.apply(A) for bc in bcs]

            solver = backend.LUSolver(A, self.method)
            self.block_helper.forward_solver = solver

        if self.assemble_system:
            system_assembler = backend.SystemAssembler(lhs, rhs, bcs)
            b = backend.Function(self.function_space).vector()
            system_assembler.assemble(b)
        else:
            b = compat.assemble_adjoint_value(rhs)
            [bc.apply(b) for bc in bcs]

        solver.parameters.update(self.lu_solver_parameters)
        solver.solve(func.vector(), b)
        return func