def derivative_outer_action( dependencies, values, variable, contraction_vector, hermitian, input, coefficient, context ): dolfin_variable = values[dependencies.index(variable)].data dolfin_values = [val.data for val in values] expressions.update_expressions(frozen_expressions) constant.update_constants(frozen_constants) current_form = backend.replace(eq_lhs, dict(zip(diag_coeffs, dolfin_values))) deriv = backend.derivative(current_form, dolfin_variable) args = ufl.algorithms.extract_arguments(deriv) deriv = backend.replace(deriv, {args[2]: contraction_vector.data}) # contract over the outer index # Assemble the G-matrix now, so that we can apply the Dirichlet BCs to it if len(ufl.algorithms.extract_arguments(ufl.algorithms.expand_derivatives(coefficient * deriv))) == 0: return adjlinalg.Vector(None) G = coefficient * deriv if hermitian: output = backend.action(backend.adjoint(G), input.data) else: output = backend.action(G, input.data) return adjlinalg.Vector(output)
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 = [utils.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_action_cb(dependencies, values, hermitian, coefficient, input, context): 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))) if hermitian: eq_l = backend.adjoint(eq_l) output = coefficient * backend.action(eq_l, input.data) return adjlinalg.Vector(output)
def __call__(self, dependencies, values): expressions.update_expressions(self.frozen_expressions) constant.update_constants(self.frozen_constants) coeffs = [x for x in ufl.algorithms.extract_coefficients(self.scheme.rhs_form()) if hasattr(x, 'function_space')] for (coeff, value) in zip(coeffs, values): coeff.assign(value.data) self.scheme.t().assign(self.time) self.solver.step(self.dt) # FIXME: This form should actually be from before the solve. out = adjlinalg.Vector(self.scheme.solution()) out.nonlinear_form = -self.dt*self.scheme.rhs_form() out.nonlinear_u = self.scheme.solution() out.nonlinear_bcs = [] out.nonlinear_J = ufl.derivative(out.nonlinear_form, out.nonlinear_u) return out
def derivative_action(self, dependencies, values, variable, contraction_vector, hermitian): expressions.update_expressions(self.frozen_expressions) constant.update_constants(self.frozen_constants) if not hermitian: if self.solver not in caching.pis_fwd_to_tlm: dolfin.info_blue("No TLM solver, creating ... ") creation_timer = dolfin.Timer("to_adm") if contraction_vector.data is not None: tlm_scheme = self.scheme.to_tlm(contraction_vector.data) else: tlm_scheme = self.scheme.to_tlm(dolfin.Function(self.fn_space)) creation_time = creation_timer.stop() dolfin.info_red("TLM creation time: %s" % creation_time) tlm_solver = dolfin.PointIntegralSolver(tlm_scheme) tlm_solver.parameters.update(self.solver.parameters) caching.pis_fwd_to_tlm[self.solver] = tlm_solver else: tlm_solver = caching.pis_fwd_to_tlm[self.solver] tlm_scheme = tlm_solver.scheme() if contraction_vector.data is not None: tlm_scheme.contraction.assign(contraction_vector.data) else: tlm_scheme.contraction.vector().zero() coeffs = [ x for x in ufl.algorithms.extract_coefficients(tlm_scheme.rhs_form()) if hasattr(x, "function_space") ] for (coeff, value) in zip(coeffs, values): coeff.assign(value.data) tlm_scheme.t().assign(self.time) tlm_solver.step(self.dt) return adjlinalg.Vector(tlm_scheme.solution()) else: if self.solver not in caching.pis_fwd_to_adj: dolfin.info_blue("No ADM solver, creating ... ") creation_timer = dolfin.Timer("to_adm") if contraction_vector.data is not None: adm_scheme = self.scheme.to_adm(contraction_vector.data) else: adm_scheme = self.scheme.to_adm(dolfin.Function(self.fn_space)) creation_time = creation_timer.stop() dolfin.info_red("ADM creation time: %s" % creation_time) adm_solver = dolfin.PointIntegralSolver(adm_scheme) adm_solver.parameters.update(self.solver.parameters) caching.pis_fwd_to_adj[self.solver] = adm_solver else: adm_solver = caching.pis_fwd_to_adj[self.solver] adm_scheme = adm_solver.scheme() if contraction_vector.data is not None: adm_scheme.contraction.assign(contraction_vector.data) else: adm_scheme.contraction.vector().zero() coeffs = [ x for x in ufl.algorithms.extract_coefficients(adm_scheme.rhs_form()) if hasattr(x, "function_space") ] for (coeff, value) in zip(coeffs, values): coeff.assign(value.data) adm_scheme.t().assign(self.time) adm_solver.step(self.dt) return adjlinalg.Vector(adm_scheme.solution())