def assign(self, receiving, giving, annotate=None):

      out = backend.FunctionAssigner.assign(self, receiving, giving)
      to_annotate = utils.to_annotate(annotate)

      if to_annotate:
        # Receiving is always a single Function, or a single Function.sub(foo).sub(bar)

        # If the user passes in v.sub(0) to this function, we need to get a handle on v;
        # fetch that now
        receiving_super = get_super_function(receiving)
        receiving_fnspace = receiving_super.function_space()
        receiving_identity = utils.get_identity_block(receiving_fnspace)
        receiving_idx = get_super_idx(receiving)

        rhs = FunctionAssignerRHS(self, self.adj_function_assigner, receiving_super, receiving_idx, giving)
        receiving_dep = adjglobals.adj_variables.next(receiving_super)

        solving.register_initial_conditions(zip(rhs.coefficients(),rhs.dependencies()), linear=True)
        if backend.parameters["adjoint"]["record_all"]:
          adjglobals.adjointer.record_variable(receiving_dep, libadjoint.MemoryStorage(adjlinalg.Vector(receiving_super)))

        eq = libadjoint.Equation(receiving_dep, blocks=[receiving_identity], targets=[receiving_dep], rhs=rhs)
        cs = adjglobals.adjointer.register_equation(eq)

        solving.do_checkpoint(cs, receiving_dep, rhs)

      return out
        def step(self, dt, annotate=None):

            to_annotate = utils.to_annotate(annotate)

            if to_annotate:
                scheme = self.scheme()
                var = scheme.solution()
                fn_space = var.function_space()

                current_var = adjglobals.adj_variables[var]
                if not adjglobals.adjointer.variable_known(current_var):
                    solving.register_initial_conditions([(var, current_var)], linear=True)

                identity_block = utils.get_identity_block(fn_space)
                frozen_expressions = expressions.freeze_dict()
                frozen_constants = constant.freeze_dict()
                rhs = PointIntegralRHS(self, dt, current_var, frozen_expressions, frozen_constants)
                next_var = adjglobals.adj_variables.next(var)

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

            super(PointIntegralSolver, self).step(dt)

            if to_annotate:
                curtime = float(scheme.t())
                scheme.t().assign(curtime)  # so that d-a sees the time update, which is implict in step

                solving.do_checkpoint(cs, next_var, rhs)

                if dolfin.parameters["adjoint"]["record_all"]:
                    adjglobals.adjointer.record_variable(next_var, libadjoint.MemoryStorage(adjlinalg.Vector(var)))
Esempio n. 3
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
Esempio n. 4
0
def register_initial_condition(coeff, dep):
  fn_space = coeff.function_space()
  identity_block = utils.get_identity_block(fn_space)

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

  init_rhs=adjlinalg.Vector(coeff).duplicate()
  init_rhs.axpy(1.0,adjlinalg.Vector(coeff))

  rhs = adjrhs.RHS(init_rhs)
  initial_eq = libadjoint.Equation(dep, blocks=[identity_block], targets=[dep], rhs=rhs)
  cs = adjglobals.adjointer.register_equation(initial_eq)
  assert adjglobals.adjointer.variable_known(dep)
  do_checkpoint(cs, dep, rhs)
Esempio n. 5
0
def register_assign(new, old, op=None):

    if not isinstance(old, backend.Function):
        assert op is not None

    fn_space = new.function_space()
    identity_block = utils.get_identity_block(fn_space)
    dep = adjglobals.adj_variables.next(new)

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

    rhs = IdentityRHS(old, fn_space, op)
    register_initial_conditions(zip(rhs.coefficients(),rhs.dependencies()), linear=True)
    initial_eq = libadjoint.Equation(dep, blocks=[identity_block], targets=[dep], rhs=rhs)
    cs = adjglobals.adjointer.register_equation(initial_eq)

    do_checkpoint(cs, dep, rhs)
Esempio n. 6
0
def dolfin_adjoint_assign(self, other, annotate=None, *args, **kwargs):
    '''We also need to monkeypatch the Function.assign method, as it is often used inside
    the main time loop, and not annotating it means you get the adjoint wrong for totally
    nonobvious reasons. If anyone objects to me monkeypatching your objects, my apologies
    in advance.'''

    if self is other:
        return

    to_annotate = utils.to_annotate(annotate)
    # if we shouldn't annotate, just assign
    if not to_annotate:
        return dolfin_assign(self, other, *args, **kwargs)

    if isinstance(other, ufl.algebra.Sum) or isinstance(other, ufl.algebra.Product):
        if backend.__name__ != 'dolfin':
            errmsg = '''Cannot use Function.assign(linear combination of other Functions) yet.'''
            raise libadjoint.exceptions.LibadjointErrorNotImplemented(errmsg)
        else:
            lincom = _check_and_contract_linear_comb(other, self)
    else:
        lincom = [(other, 1.0)]

    # ignore anything not a backend.Function, unless the user insists
    if not isinstance(other, backend.Function) and (annotate is not True):
        return dolfin_assign(self, other, *args, **kwargs)

    # ignore anything that is an interpolation, rather than a straight assignment
    if hasattr(self, "function_space") and hasattr(other, "function_space"):
        if str(self.function_space()) != str(other.function_space()):
            return dolfin_assign(self, other, *args, **kwargs)


    functions, weights = zip(*lincom)

    self_var = adjglobals.adj_variables[self]
    function_vars = [adjglobals.adj_variables[function] for function in functions]

    # ignore any functions we haven't seen before -- we DON'T want to
    # annotate the assignment of initial conditions here. That happens
    # in the main solve wrapper.
    for function_var in function_vars:
        if not adjglobals.adjointer.variable_known(function_var) and not adjglobals.adjointer.variable_known(self_var) and (annotate is not True):
            [adjglobals.adj_variables.forget(function) for function in functions]
            adjglobals.adj_variables.forget(self)

            return dolfin_assign(self, other, *args, **kwargs)

    # OK, so we have a variable we've seen before. Beautiful.
    if not adjglobals.adjointer.variable_known(self_var):
        adjglobals.adj_variables.forget(self)

    out = dolfin_assign(self, other, *args, **kwargs)

    fn_space = self.function_space()
    identity_block = utils.get_identity_block(fn_space)
    dep = adjglobals.adj_variables.next(self)

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

    rhs = LinComRHS(functions, weights, fn_space)
    register_initial_conditions(zip(rhs.coefficients(),rhs.dependencies()), linear=True)
    initial_eq = libadjoint.Equation(dep, blocks=[identity_block], targets=[dep], rhs=rhs)
    cs = adjglobals.adjointer.register_equation(initial_eq)

    do_checkpoint(cs, dep, rhs)

    return out