Ejemplo n.º 1
0
def interpolate(v, V, annotate=None, name=None):
    '''The interpolate call changes Function data, and so it too must be annotated so that the
    adjoint and tangent linear models may be constructed automatically by libadjoint.

    To disable the annotation of this function, just pass :py:data:`annotate=False`. This is useful in
    cases where the interpolation is known to be irrelevant or diagnostic for the purposes of the adjoint
    computation (such as interpolating fields to other function spaces for the purposes of
    visualisation).'''

    out = backend.interpolate(v, V)
    if name is not None:
        out.adj_name = name

    to_annotate = utils.to_annotate(annotate)

    if isinstance(v, backend.Function) and to_annotate:
        rhsdep = adjglobals.adj_variables[v]
        if adjglobals.adjointer.variable_known(rhsdep):
            rhs = InterpolateRHS(v, V)
            identity_block = utils.get_identity_block(V)

            solving.register_initial_conditions(zip(rhs.coefficients(),rhs.dependencies()), linear=True)

            dep = adjglobals.adj_variables.next(out)

            if backend.parameters["adjoint"]["record_all"]:
                adjglobals.adjointer.record_variable(dep, libadjoint.MemoryStorage(adjlinalg.Vector(out)))

            initial_eq = libadjoint.Equation(dep, blocks=[identity_block], targets=[dep], rhs=rhs)
            cs = adjglobals.adjointer.register_equation(initial_eq)

            solving.do_checkpoint(cs, dep, rhs)

    return out
Ejemplo n.º 2
0
def interpolate(*args, **kwargs):
    """Interpolation is overloaded to ensure that the returned Function object is overloaded.
    We are not able to annotate the interpolation call at the moment.

    """
    output = backend.interpolate(*args, **kwargs)
    return create_overloaded_object(output)
Ejemplo n.º 3
0
    def evaluate_adj_component(self,
                               inputs,
                               adj_inputs,
                               block_variable,
                               idx,
                               prepared=None):
        adj_inputs = adj_inputs[0]
        c = block_variable.output
        if c not in self.expression.user_defined_derivatives:
            return None

        for key in self.expression._ad_attributes_dict:
            if key not in self.expression.ad_ignored_attributes:
                setattr(self.expression.user_defined_derivatives[c], key,
                        self.expression._ad_attributes_dict[key])

        adj_output = None
        for adj_pair in adj_inputs:
            adj_input = adj_pair[0]
            V = adj_pair[1]
            if adj_output is None:
                adj_output = 0.0

            interp = backend.interpolate(
                self.expression.user_defined_derivatives[c], V)
            if isinstance(c, (backend.Constant, AdjFloat)):
                adj_output += adj_input.inner(interp.vector())
            else:
                vec = adj_input * interp.vector()
                adj_func = backend.Function(V, vec)

                num_sub_spaces = V.num_sub_spaces()
                if num_sub_spaces > 1:
                    for i in range(num_sub_spaces):
                        adj_output += backend.interpolate(
                            adj_func.sub(i), c.function_space()).vector()
                else:
                    adj_output += backend.interpolate(
                        adj_func, c.function_space()).vector()
        return adj_output
Ejemplo n.º 4
0
def interpolate(v, V, annotate=None, name=None):
    '''The interpolate call changes Function data, and so it too must be annotated so that the
    adjoint and tangent linear models may be constructed automatically by libadjoint.

    To disable the annotation of this function, just pass :py:data:`annotate=False`. This is useful in
    cases where the interpolation is known to be irrelevant or diagnostic for the purposes of the adjoint
    computation (such as interpolating fields to other function spaces for the purposes of
    visualisation).'''

    out = backend.interpolate(v, V)
    out = utils.function_to_da_function(out)
    if name is not None:
        out.adj_name = name

    to_annotate = utils.to_annotate(annotate)

    if to_annotate:
        if isinstance(v, backend.Function):
            rhsdep = adjglobals.adj_variables[v]
            if adjglobals.adjointer.variable_known(rhsdep):
                rhs = InterpolateRHS(v, V)
                identity_block = utils.get_identity_block(V)

                solving.register_initial_conditions(zip(
                    rhs.coefficients(), rhs.dependencies()),
                                                    linear=True)

                dep = adjglobals.adj_variables.next(out)

                if backend.parameters["adjoint"]["record_all"]:
                    adjglobals.adjointer.record_variable(
                        dep, libadjoint.MemoryStorage(adjlinalg.Vector(out)))

                initial_eq = libadjoint.Equation(dep,
                                                 blocks=[identity_block],
                                                 targets=[dep],
                                                 rhs=rhs)
                cs = adjglobals.adjointer.register_equation(initial_eq)

                solving.do_checkpoint(cs, dep, rhs)

        elif annotate is not None:
            outvar = adjglobals.adj_variables[out]
            solving.register_initial_conditions([
                [out, outvar],
            ], linear=True)

    return out
Ejemplo n.º 5
0
    def derivative_action(self, dependencies, values, variable, contraction_vector, hermitian):
        if not hermitian:
            return adjlinalg.Vector(backend.interpolate(contraction_vector.data, self.V))
        else:
#      For future reference, the transpose action of the interpolation operator
#      is (in pseudocode!):
#
#      for target_dof in target:
#        figure out what element it lives in, to compute src_dofs
#        for src_dof in src_dofs:
#          basis = the value of the basis function of src_dof at the node of target_dof
#
#          # all of the above is exactly the same as the forward interpolation.
#          # forward interpolation would do:
#          # target_coefficients[target_dof] += basis * src_coefficients[src_dof]
#
#          # but the adjoint action is:
#          src_coefficients[src_dof] += basis * target_coefficients[target_dof]

            raise libadjoint.exceptions.LibadjointErrorNotImplemented("Can't transpose an interpolation operator yet, sorry!")
Ejemplo n.º 6
0
    def derivative_action(self, dependencies, values, variable,
                          contraction_vector, hermitian):
        if not hermitian:
            return adjlinalg.Vector(
                backend.interpolate(contraction_vector.data, self.V))
        else:
            #      For future reference, the transpose action of the interpolation operator
            #      is (in pseudocode!):
            #
            #      for target_dof in target:
            #        figure out what element it lives in, to compute src_dofs
            #        for src_dof in src_dofs:
            #          basis = the value of the basis function of src_dof at the node of target_dof
            #
            #          # all of the above is exactly the same as the forward interpolation.
            #          # forward interpolation would do:
            #          # target_coefficients[target_dof] += basis * src_coefficients[src_dof]
            #
            #          # but the adjoint action is:
            #          src_coefficients[src_dof] += basis * target_coefficients[target_dof]

            raise libadjoint.exceptions.LibadjointErrorNotImplemented(
                "Can't transpose an interpolation operator yet, sorry!")
Ejemplo n.º 7
0
    def evaluate_hessian_component(self,
                                   inputs,
                                   hessian_inputs,
                                   adj_inputs,
                                   block_variable,
                                   idx,
                                   relevant_dependencies,
                                   prepared=None):
        hessian_inputs = hessian_inputs[0]
        adj_inputs = adj_inputs[0]
        c1 = block_variable.output

        if c1 not in self.expression.user_defined_derivatives:
            return None

        first_deriv = self.expression.user_defined_derivatives[c1]
        for key in self.expression._ad_attributes_dict:
            if key not in self.expression.ad_ignored_attributes:
                setattr(first_deriv, key,
                        self.expression._ad_attributes_dict[key])

        hessian_output = None
        for _, bo2 in relevant_dependencies:
            c2 = bo2.output
            tlm_input = bo2.tlm_value

            if tlm_input is None:
                continue

            if c2 not in first_deriv.user_defined_derivatives:
                continue

            second_deriv = first_deriv.user_defined_derivatives[c2]
            for key in self.expression._ad_attributes_dict:
                if key not in self.expression.ad_ignored_attributes:
                    setattr(second_deriv, key,
                            self.expression._ad_attributes_dict[key])

            for adj_pair in adj_inputs:
                adj_input = adj_pair[0]
                V = adj_pair[1]

                if hessian_output is None:
                    hessian_output = 0.0

                # TODO: Seems we can only project and not interpolate ufl.algebra.Product in dolfin.
                #       Consider the difference and which actually makes sense here.
                interp = backend.project(tlm_input * second_deriv, V)
                if isinstance(c1, (backend.Constant, AdjFloat)):
                    hessian_output += adj_input.inner(interp.vector())
                else:
                    vec = adj_input * interp.vector()
                    hessian_func = backend.Function(V, vec)

                    num_sub_spaces = V.num_sub_spaces()
                    if num_sub_spaces > 1:
                        for i in range(num_sub_spaces):
                            hessian_output += backend.interpolate(
                                hessian_func.sub(i),
                                c1.function_space()).vector()
                    else:
                        hessian_output += backend.interpolate(
                            hessian_func, c1.function_space()).vector()

        for hessian_pair in hessian_inputs:
            if hessian_output is None:
                hessian_output = 0.0
            hessian_input = hessian_pair[0]
            V = hessian_pair[1]

            interp = backend.interpolate(first_deriv, V)
            if isinstance(c1, (backend.Constant, AdjFloat)):
                hessian_output += hessian_input.inner(interp.vector())
            else:
                vec = hessian_input * interp.vector()
                hessian_func = backend.Function(V, vec)

                num_sub_spaces = V.num_sub_spaces()
                if num_sub_spaces > 1:
                    for i in range(num_sub_spaces):
                        hessian_output += backend.interpolate(
                            hessian_func.sub(i), c1.function_space()).vector()
                else:
                    hessian_output += backend.interpolate(
                        hessian_func, c1.function_space()).vector()
        return hessian_output
Ejemplo n.º 8
0
 def __call__(self, dependencies, values):
     return adjlinalg.Vector(backend.interpolate(values[0].data, self.V))
Ejemplo n.º 9
0
 def __call__(self, dependencies, values):
     return adjlinalg.Vector(backend.interpolate(values[0].data, self.V))