def __init__(self, functional, controls, solver): self.solver = solver if not isinstance(solver, Solver): raise ValueError, "solver argument of wrong type." self._functional = functional if not isinstance(functional, PrototypeFunctional): raise ValueError, "invalid functional argument." # Hidden attributes self._solver_params = solver.parameters self._problem_params = solver.problem.parameters self._time_integrator = None # Controls self.controls = enlisting.enlist(controls) # Conform to dolfin-adjoint API self.scale = 1 self.eval_cb_pre = lambda *args: None self.eval_cb_post = lambda *args: None self.derivative_cb_pre = lambda *args: None self.derivative_cb_post = lambda *args: None self.replay_cb = lambda *args: None self.hessian_cb = lambda *args: None self.cache = None self.current_func_value = None self.hessian = None self.functional = Functional(None)
def derivative(self, forget=False, **kwargs): """ Computes the first derivative of the functional with respect to its controls by solving the adjoint equations. """ log(INFO, 'Start evaluation of dj') timer = Timer("dj evaluation") self.functional = self.time_integrator.dolfin_adjoint_functional(self.solver.state) dj = compute_gradient(self.functional, self.controls, forget=forget, **kwargs) parameters["adjoint"]["stop_annotating"] = False log(INFO, "Runtime: " + str(timer.stop()) + " s") return enlisting.enlist(dj)
def derivative(self, forget=False, **kwargs): """ Computes the first derivative of the functional with respect to its controls by solving the adjoint equations. """ log(INFO, 'Start evaluation of dj') timer = Timer("dj evaluation") if not hasattr(self, "time_integrator"): self.evaluate() self.functional = self.time_integrator.dolfin_adjoint_functional( self.solver.state) dj = compute_gradient(self.functional, self.controls, forget=forget, **kwargs) parameters["adjoint"]["stop_annotating"] = False log(INFO, "Runtime: " + str(timer.stop()) + " s") return enlisting.enlist(dj)
def __call__(self, value): """ Evaluates the reduced functional for the given control value. Args: value: The point in control space where to perform the Taylor test. Must be of the same type as the Control (e.g. Function, Constant or lists of latter). Returns: float: The functional value. """ value = enlisting.enlist(value) # Update the control values. # Note that we do not update the control values on the tape, # because OpenTidalFarm reannotates the tape in each iteration. for c, v in zip(self.controls, value): vec = c.coeff.vector() if vec.id() == v.vector().id(): continue vec.zero() vec.axpy(1, v.vector()) return self.evaluate()