Exemplo n.º 1
0
def adjoint(form, reordered_arguments = None, adjoint_arguments = None):
    """
    Wrapper for the DOLFIN adjoint function. Accepts the additional optional
    adjoint_arguments, which if supplied should be a tuple of Argument s
    corresponding to the adjoint test and trial functions. Correctly handles
    QForm s.
    """

    if adjoint_arguments is None:
        a_form = dolfin.adjoint(form, reordered_arguments = reordered_arguments)
    elif not reordered_arguments is None:
        raise InvalidArgumentException("Cannot supply both reordered_arguments and adjoint_arguments keyword arguments")
    else:
        if not len(adjoint_arguments) == 2 \
          or not isinstance(adjoint_arguments[0], ufl.argument.Argument) \
          or not isinstance(adjoint_arguments[1], ufl.argument.Argument):
            raise InvalidArgumentException("adjoint_arguments must be a pair of Argument s")

        a_test, a_trial = adjoint_arguments
        a_form = dolfin.adjoint(form)
        test, trial = extract_test_and_trial(a_form)

        if not test.element() == a_test.element() or not trial.element() == a_trial.element():
            raise InvalidArgumentException("Invalid adjoint_arguments")
        a_form = replace(a_form, {test:a_test, trial:a_trial})

    if isinstance(form, QForm):
        return QForm(a_form, quadrature_degree = form.quadrature_degree())
    else:
        return a_form
def transpose_operators(operators):
    out = [None, None]

    for i in range(2):
        op = operators[i]

        if op is None:
            out[i] = None
        elif isinstance(op, dolfin.cpp.GenericMatrix):
            out[i] = op.__class__()
            dolfin.assemble(dolfin.adjoint(op.form), tensor=out[i])

            if hasattr(op, 'bcs'):
                adjoint_bcs = [utils.homogenize(bc) for bc in op.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in op.bcs if not isinstance(bc, dolfin.DirichletBC)]
                [bc.apply(out[i]) for bc in adjoint_bcs]

        elif isinstance(op, dolfin.Form) or isinstance(op, ufl.form.Form):
            out[i] = dolfin.adjoint(op)

            if hasattr(op, 'bcs'):
                out[i].bcs = [utils.homogenize(bc) for bc in op.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in op.bcs if not isinstance(bc, dolfin.DirichletBC)]

        elif isinstance(op, AdjointKrylovMatrix):
            pass

        else:
            print "op.__class__: ", op.__class__
            raise libadjoint.exceptions.LibadjointErrorNotImplemented("Don't know how to transpose anything else!")

    return out
def adjoint(form, reordered_arguments=None, adjoint_arguments=None):
    """
    Wrapper for the DOLFIN adjoint function. Accepts the additional optional
    adjoint_arguments, which if supplied should be a tuple of Argument s
    corresponding to the adjoint test and trial functions.
    """

    if adjoint_arguments is None:
        a_form = dolfin.adjoint(form, reordered_arguments=reordered_arguments)
    elif not reordered_arguments is None:
        raise InvalidArgumentException(
            "Cannot supply both reordered_arguments and adjoint_arguments keyword arguments"
        )
    else:
        if not len(adjoint_arguments) == 2 \
          or not isinstance(adjoint_arguments[0], ufl.argument.Argument) \
          or not isinstance(adjoint_arguments[1], ufl.argument.Argument):
            raise InvalidArgumentException(
                "adjoint_arguments must be a pair of Argument s")

        a_test, a_trial = adjoint_arguments
        a_form = dolfin.adjoint(form)
        test, trial = extract_test_and_trial(a_form)

        if not test.element() == a_test.element() or not trial.element(
        ) == a_trial.element():
            raise InvalidArgumentException("Invalid adjoint_arguments")
        a_form = dolfin.replace(a_form, {test: a_test, trial: a_trial})

    return a_form
Exemplo n.º 4
0
 def _assemble_operator_for_stability_factor_impl(self_, term):
     if term == "stability_factor_left_hand_matrix":
         return tuple(f + adjoint(f) for f in assemble_operator(self_, "a"))
     elif term == "stability_factor_right_hand_matrix":
         return assemble_operator(self_, "inner_product")
     elif term == "stability_factor_dirichlet_bc":
         original_dirichlet_bcs = assemble_operator(self_, "dirichlet_bc")
         zeroed_dirichlet_bcs = list()
         for original_dirichlet_bc in original_dirichlet_bcs:
             zeroed_dirichlet_bc = list()
             for original_dirichlet_bc_i in original_dirichlet_bc:
                 args = list()
                 args.append(original_dirichlet_bc_i.function_space())
                 zero_value = Constant(
                     zeros(original_dirichlet_bc_i.value().ufl_shape))
                 args.append(zero_value)
                 args.extend(original_dirichlet_bc_i._domain)
                 kwargs = original_dirichlet_bc_i._kwargs
                 zeroed_dirichlet_bc.append(DirichletBC(*args, **kwargs))
             assert len(zeroed_dirichlet_bc) == len(original_dirichlet_bc)
             zeroed_dirichlet_bcs.append(zeroed_dirichlet_bc)
         assert len(zeroed_dirichlet_bcs) == len(original_dirichlet_bcs)
         return tuple(zeroed_dirichlet_bcs)
     else:
         return assemble_operator(self_, term)
Exemplo n.º 5
0
    def assembleA(self, x, assemble_adjoint=False, assemble_rhs=False):
        """
        Assemble the matrices and rhs for the forward/adjoint problems
        """
        trial = dl.TrialFunction(self.Vh[STATE])
        test = dl.TestFunction(self.Vh[STATE])
        c = vector2Function(x[PARAMETER], self.Vh[PARAMETER])
        Avarf = dl.inner(
            dl.exp(c) * dl.nabla_grad(trial), dl.nabla_grad(test)) * dl.dx
        if not assemble_adjoint:
            bform = dl.inner(self.f, test) * dl.dx
            Matrix, rhs = dl.assemble_system(Avarf, bform, self.bc)
        else:
            # Assemble the adjoint of A (i.e. the transpose of A)
            s = vector2Function(x[STATE], self.Vh[STATE])
            bform = dl.inner(dl.Constant(0.), test) * dl.dx
            Matrix, _ = dl.assemble_system(dl.adjoint(Avarf), bform, self.bc0)
            Bu = -(self.B * x[STATE])
            Bu += self.u_o
            rhs = dl.Vector()
            self.B.init_vector(rhs, 1)
            self.B.transpmult(Bu, rhs)
            rhs *= 1.0 / self.noise_variance

        if assemble_rhs:
            return Matrix, rhs
        else:
            return Matrix
Exemplo n.º 6
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)
Exemplo n.º 7
0
    def compile_adjoint_jacobian(self):
        """Compute the adjoint of the first variation of the constraint form.

        This method only has side effects.
        """
        self.compile_constraint_jacobian()
        self.__adjoint_jacobian = adjoint(self.__constraint_jacobian)
        return
Exemplo n.º 8
0
def transpose_operators(operators):
    out = [None, None]

    for i in range(2):
        op = operators[i]

        if op is None:
            out[i] = None
        elif isinstance(op, dolfin.cpp.GenericMatrix):
            out[i] = op.__class__()
            dolfin.assemble(dolfin.adjoint(op.form), tensor=out[i])

            if hasattr(op, 'bcs'):
                adjoint_bcs = [
                    utils.homogenize(bc)
                    for bc in op.bcs if isinstance(bc, dolfin.cpp.DirichletBC)
                ] + [
                    bc
                    for bc in op.bcs if not isinstance(bc, dolfin.DirichletBC)
                ]
                [bc.apply(out[i]) for bc in adjoint_bcs]

        elif isinstance(op, dolfin.Form) or isinstance(op, ufl.form.Form):
            out[i] = dolfin.adjoint(op)

            if hasattr(op, 'bcs'):
                out[i].bcs = [
                    utils.homogenize(bc)
                    for bc in op.bcs if isinstance(bc, dolfin.cpp.DirichletBC)
                ] + [
                    bc
                    for bc in op.bcs if not isinstance(bc, dolfin.DirichletBC)
                ]

        elif isinstance(op, AdjointKrylovMatrix):
            pass

        else:
            print("op.__class__: ", op.__class__)
            raise libadjoint.exceptions.LibadjointErrorNotImplemented(
                "Don't know how to transpose anything else!")

    return out
Exemplo n.º 9
0
    def set_forms(self, unknown, geom_ord=[0]):
        """
        Set up weak forms of elliptic PDE.
        """
        if any(s >= 0 for s in geom_ord):
            ## forms for forward equation ##
            # 4. Define variational problem
            # functions
            if not hasattr(self, 'states_fwd'):
                self.states_fwd = df.Function(self.W)
            # u, l = df.split(self.states_fwd)
            u, l = df.TrialFunctions(self.W)
            v, m = df.TestFunctions(self.W)
            f = self._source_term(degree=2)
            # variational forms
            if 'true' in str(type(unknown)):
                unknown = df.interpolate(unknown, self.V)
            self.F = df.exp(unknown) * df.inner(
                df.grad(u), df.grad(v)) * df.dx + (
                    u * m + v *
                    l) * self.ds - f * v * df.dx + self.nugg * l * m * df.dx
#             self.dFdstates = df.derivative(self.F, self.states_fwd) # Jacobian
#             self.a = unknown*df.inner(df.grad(u), df.grad(v))*df.dx + (u*m + v*l)*self.ds + self.nugg*l*m*df.dx
#             self.L = f*v*df.dx
        if any(s >= 1 for s in geom_ord):
            ## forms for adjoint equation ##
            # Set up the objective functional J
            #             u,_,_ = df.split(self.states_fwd)
            #             J_form = obj.form(u)
            # Compute adjoint of forward operator
            F2 = df.action(self.F, self.states_fwd)
            self.dFdstates = df.derivative(
                F2, self.states_fwd)  # linearized forward operator
            args = ufl.algorithms.extract_arguments(
                self.dFdstates)  # arguments for bookkeeping
            self.adj_dFdstates = df.adjoint(
                self.dFdstates, reordered_arguments=args
            )  # adjoint linearized forward operator
            #             self.dJdstates = df.derivative(J_form, self.states_fwd, df.TestFunction(self.W)) # derivative of functional with respect to solution
            #             self.dirac_1 = obj.ptsrc(u,1) # dirac_1 cannot be initialized here because it involves evaluation
            ## forms for gradient ##
            self.dFdunknown = df.derivative(F2, unknown)
            self.adj_dFdunknown = df.adjoint(self.dFdunknown)
Exemplo n.º 10
0
def is_self_adjoint_form(form):
    """
    Return True if the supplied Form is self-adjoint. May return false negatives.
    """

    if not isinstance(form, ufl.form.Form):
        raise InvalidArgumentException("form must be a Form")

    a_form = dolfin.adjoint(form)

    test, trial = extract_test_and_trial(form)
    a_test, a_trial = extract_test_and_trial(a_form)

    if not test.element() == a_trial.element():
        return False
    elif not trial.element() == a_test.element():
        return False

    a_form = dolfin.replace(a_form, {a_test:trial, a_trial:test})

    return expand(form) == expand(a_form)
Exemplo n.º 11
0
def is_self_adjoint_form(form):
    """
    Return True if the supplied Form is self-adjoint. May return false negatives.
    """

    if not isinstance(form, ufl.form.Form):
        raise InvalidArgumentException("form must be a Form")

    a_form = dolfin.adjoint(form)

    test, trial = extract_test_and_trial(form)
    a_test, a_trial = extract_test_and_trial(a_form)

    if not test.element() == a_trial.element():
        return False
    elif not trial.element() == a_test.element():
        return False

    a_form = dolfin.replace(a_form, {a_test:trial, a_trial:test})

    return expand(form) == expand(a_form)
Exemplo n.º 12
0
 def assembleA(self,x, assemble_adjoint = False, assemble_rhs = False):
     """
     Assemble the matrices and rhs for the forward/adjoint problems
     """
     trial = dl.TrialFunction(self.Vh[STATE])
     test = dl.TestFunction(self.Vh[STATE])
     m = vector2Function(x[PARAMETER], self.Vh[PARAMETER])
     Avarf = ufl.inner(ufl.exp(m)*sigma(trial), strain(test))*ufl.dx
     if not assemble_adjoint:
         bform = ufl.inner(self.f, test)*ufl.dx
         Matrix, rhs = dl.assemble_system(Avarf, bform, self.bc)
     else:
         # Assemble the adjoint of A (i.e. the transpose of A)
         u = vector2Function(x[STATE], self.Vh[STATE])
         obs = vector2Function(self.u_o, self.Vh[STATE])
         bform = ufl.inner(obs - u, test)*ufl.dx
         Matrix, rhs = dl.assemble_system(dl.adjoint(Avarf), bform, self.bc0)
         
     if assemble_rhs:
         return Matrix, rhs
     else:
         return Matrix
Exemplo n.º 13
0
 def assembleA(self,x, assemble_adjoint = False, assemble_rhs = False):
     """
     Assemble the matrices and rhs for the forward/adjoint problems
     """
     trial = dl.TrialFunction(self.Vh[STATE])
     test = dl.TestFunction(self.Vh[STATE])
     m = vector2Function(x[PARAMETER], self.Vh[PARAMETER])
     Avarf = dl.inner(dl.exp(m)*dl.grad(trial), dl.grad(test))*dl.dx
     if not assemble_adjoint:
         bform = dl.inner(self.f, test)*dl.dx
         Matrix, rhs = dl.assemble_system(Avarf, bform, self.bc)
     else:
         # Assemble the adjoint of A (i.e. the transpose of A)
         u = vector2Function(x[STATE], self.Vh[STATE])
         obs = vector2Function(self.u_o, self.Vh[STATE])
         bform = dl.inner(obs - u, test)*dl.dx
         Matrix, rhs = dl.assemble_system(dl.adjoint(Avarf), bform, self.bc0)
         
     if assemble_rhs:
         return Matrix, rhs
     else:
         return Matrix