Example #1
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, backend.cpp.GenericMatrix):
      out[i] = op.__class__()
      backend.assemble(backend.adjoint(op.form), tensor=out[i])

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

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

      if hasattr(op, 'bcs'):
        out[i].bcs = [backend.homogenize(bc) for bc in op.bcs if isinstance(bc, backend.cpp.DirichletBC)] + [bc for bc in op.bcs if not isinstance(bc, backend.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
Example #2
0
  def solve(self, var, b):
    timer = backend.Timer("Matrix-free solver")
    solver = backend.PETScKrylovSolver(*self.solver_parameters)
    solver.parameters.update(self.parameters)

    x = backend.Function(self.fn_space)
    if b.data is None:
      backend.info_red("Warning: got zero RHS for the solve associated with variable %s" % var)
      return adjlinalg.Vector(x)

    if isinstance(b.data, backend.Function):
      rhs = b.data.vector().copy()
    else:
      rhs = backend.assemble(b.data)

    if var.type in ['ADJ_TLM', 'ADJ_ADJOINT']:
      self.bcs = [backend.homogenize(bc) for bc in self.bcs if isinstance(bc, backend.cpp.DirichletBC)] + [bc for bc in self.bcs if not isinstance(bc, backend.DirichletBC)]

    for bc in self.bcs:
      bc.apply(rhs)

    if self.operators[1] is not None: # we have a user-supplied preconditioner
      solver.set_operators(self.data, self.operators[1])
      solver.solve(backend.down_cast(x.vector()), backend.down_cast(rhs))
    else:
      solver.solve(self.data, backend.down_cast(x.vector()), backend.down_cast(rhs))

    timer.stop()
    return adjlinalg.Vector(x)
Example #3
0
  def diag_assembly_cb(dependencies, values, hermitian, coefficient, context):
    '''This callback must conform to the libadjoint Python block assembly
    interface. It returns either the form or its transpose, depending on
    the value of the logical hermitian.'''

    assert coefficient == 1

    value_coeffs=[v.data for v in values]
    expressions.update_expressions(frozen_expressions)
    constant.update_constants(frozen_constants)
    eq_l = backend.replace(eq_lhs, dict(zip(diag_coeffs, value_coeffs)))

    kwargs = {"cache": eq_l in caching.assembled_fwd_forms} # should we cache our matrices on the way backwards?

    if hermitian:
      # Homogenise the adjoint boundary conditions. This creates the adjoint
      # solution associated with the lifted discrete system that is actually solved.
      adjoint_bcs = [backend.homogenize(bc) for bc in eq_bcs if isinstance(bc, backend.DirichletBC)] + [bc for bc in eq_bcs if not isinstance(bc, backend.DirichletBC)]
      if len(adjoint_bcs) == 0:
        adjoint_bcs = None
      else:
        adjoint_bcs = misc.uniq(adjoint_bcs)

      kwargs['bcs'] = adjoint_bcs
      kwargs['solver_parameters'] = solver_parameters
      kwargs['adjoint'] = True

      if initial_guess:
        kwargs['initial_guess'] = value_coeffs[dependencies.index(initial_guess_var)]

      if replace_map:
        kwargs['replace_map'] = dict(zip(diag_coeffs, value_coeffs))

      return (matrix_class(backend.adjoint(eq_l, reordered_arguments=ufl.algorithms.extract_arguments(eq_l)), **kwargs), adjlinalg.Vector(None, fn_space=u.function_space()))
    else:

      kwargs['bcs'] = misc.uniq(eq_bcs)
      kwargs['solver_parameters'] = solver_parameters
      kwargs['adjoint'] = False

      if initial_guess:
        kwargs['initial_guess'] = value_coeffs[dependencies.index(initial_guess_var)]

      if replace_map:
        kwargs['replace_map'] = dict(zip(diag_coeffs, value_coeffs))

      return (matrix_class(eq_l, **kwargs), adjlinalg.Vector(None, fn_space=u.function_space()))
  def diag_assembly_cb(dependencies, values, hermitian, coefficient, context):
    '''This callback must conform to the libadjoint Python block assembly
    interface. It returns either the form or its transpose, depending on
    the value of the logical hermitian.'''

    assert coefficient == 1

    expressions.update_expressions(frozen_expressions_dict)
    value_coeffs=[v.data for v in values]
    eq_l = eq_lhs

    if hermitian:
      adjoint_bcs = [backend.homogenize(bc) for bc in bcs if isinstance(bc, backend.DirichletBC)] + [bc for bc in bcs if not isinstance(bc, backend.DirichletBC)]
      if len(adjoint_bcs) == 0: adjoint_bcs = None
      return (adjlinalg.Matrix(backend.adjoint(eq_l), bcs=adjoint_bcs), adjlinalg.Vector(None, fn_space=fn_space))
    else:
      return (adjlinalg.Matrix(eq_l, bcs=bcs), adjlinalg.Vector(None, fn_space=fn_space))
Example #5
0
  def derivative_assembly(self, dependencies, values, variable, hermitian):
    replace_map = {}

    for i in range(len(self.deps)):
      if self.deps[i] == self.ic_var: continue
      j = dependencies.index(self.deps[i])
      replace_map[self.coeffs[i]] = values[j].data

    diff_var = values[dependencies.index(variable)].data

    current_form = backend.replace(self.form, replace_map)
    deriv = backend.derivative(current_form, diff_var)

    if hermitian:
      deriv = backend.adjoint(deriv)
      bcs = [backend.homogenize(bc) for bc in self.bcs if isinstance(bc, backend.DirichletBC)] + [bc for bc in self.bcs if not isinstance(bc, backend.DirichletBC)]
    else:
      bcs = self.bcs

    return adjlinalg.Matrix(deriv, bcs=bcs)
Example #6
0
 def hermitian(self):
   adjoint_bcs = [backend.homogenize(bc) for bc in self.bcs if isinstance(bc, backend.cpp.DirichletBC)] + [bc for bc in self.bcs if not isinstance(bc, backend.DirichletBC)]
   return AdjointKrylovMatrix(backend.adjoint(self.original_form), bcs=adjoint_bcs)