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 diag_action_cb(dependencies, values, hermitian, coefficient, input, context): expressions.update_expressions(frozen_expressions_dict) A.set_dependencies(dependencies, [val.data for val in values]) if hermitian: acting_mat = A.transpose() else: acting_mat = A output_fn = backend.Function(input.data.function_space()) acting_mat.mult(input.data.vector(), output_fn.vector()) vec = output_fn.vector() for i in range(len(vec)): vec[i] = coefficient * vec[i] return adjlinalg.Vector(output_fn)
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 = [utils.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))
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 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) if len(dependencies) > 0: A.set_dependencies(dependencies, [val.data for val in values]) if hermitian: A_transpose = A.hermitian() return (MatrixFree(A_transpose, fn_space=x.function.function_space(), bcs=A_transpose.bcs, solver_parameters=self.solver_parameters, operators=transpose_operators(self.operators), parameters=frozen_parameters), adjlinalg.Vector(None, fn_space=x.function.function_space())) else: return (MatrixFree(A, fn_space=x.function.function_space(), bcs=b.bcs, solver_parameters=self.solver_parameters, operators=self.operators, parameters=frozen_parameters), adjlinalg.Vector(None, fn_space=x.function.function_space()))
def derivative_action(dependencies, values, variable, contraction_vector, hermitian, input, coefficient, context): expressions.update_expressions(frozen_expressions_dict) A.set_dependencies(dependencies, [val.data for val in values]) action = A.derivative_action(values[dependencies.index(variable)].data, contraction_vector.data, hermitian, input.data, coefficient) return adjlinalg.Vector(action)
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())