def project_firedrake(v, V, **kwargs): annotate = kwargs.pop("annotate", None) to_annotate = utils.to_annotate(annotate) if isinstance(v, backend.Expression) and (annotate is not True): to_annotate = False if isinstance(v, backend.Constant) and (annotate is not True): to_annotate = False if isinstance(V, backend.functionspaceimpl.WithGeometry): result = utils.function_to_da_function(backend.Function(V, name=None)) elif isinstance(V, backend.function.Function): result = utils.function_to_da_function(V) else: raise ValueError("Can't project into a '%r'" % V) name = kwargs.pop("name", None) if name is not None: result.adj_name = name result.rename(name, "a Function from dolfin-adjoint") with misc.annotations(to_annotate): result = backend.project(v, result, **kwargs) return result
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 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
def data(self): if self.value is not None: return self.value else: x = adjglobals.adjointer.get_variable_value(self.var).data x = utils.function_to_da_function(x) return x
def project_dolfin(v, V=None, bcs=None, mesh=None, solver_type="cg", preconditioner_type="default", form_compiler_parameters=None, annotate=None, name=None): '''The project call performs an equation solve, 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 solve is known to be irrelevant or diagnostic for the purposes of the adjoint computation (such as projecting fields to other function spaces for the purposes of visualisation).''' to_annotate = utils.to_annotate(annotate) if isinstance(v, backend.Expression) and (annotate is not True): to_annotate = False if isinstance(v, backend.Constant) and (annotate is not True): to_annotate = False out = backend.project(v=v, V=V, bcs=bcs, mesh=mesh, solver_type=solver_type, preconditioner_type=preconditioner_type, form_compiler_parameters=form_compiler_parameters) out = utils.function_to_da_function(out) if name is not None: out.adj_name = name out.rename(name, "a Function from dolfin-adjoint") if to_annotate: # reproduce the logic from project. This probably isn't future-safe, but anyway if V is None: V = backend.fem.projection._extract_function_space(v, mesh) if mesh is None: mesh = V.mesh() # Define variational problem for projection w = backend.TestFunction(V) Pv = backend.TrialFunction(V) a = backend.inner(w, Pv)*backend.dx(domain=mesh) L = backend.inner(w, v)*backend.dx(domain=mesh) solving.annotate(a == L, out, bcs, solver_parameters={"linear_solver": solver_type, "preconditioner": preconditioner_type, "symmetric": True}) if backend.parameters["adjoint"]["record_all"]: adjglobals.adjointer.record_variable(adjglobals.adj_variables[out], libadjoint.MemoryStorage(adjlinalg.Vector(out))) return out
def copy(self, *args, **kwargs): name = kwargs.pop("name", None) annotate = kwargs.pop("annotate", None) to_annotate = utils.to_annotate(annotate) with misc.annotations(False): copy = backend.Function.copy(self, *args, **kwargs) copy = utils.function_to_da_function(copy) if name is not None: copy.adj_name = name copy.rename(name, "a Function from dolfin-adjoint") adjglobals.function_names.add(name) if to_annotate: assignment.register_assign(copy, self) return copy