def step(self): r"""Perform a backtracking line search for the next value of the solution and compute the search direction for the next step""" E = self.problem.E u = self.problem.u v = self.v t = self.t t.assign(1.) E_0 = self.problem.assemble(E) slope = self.problem.assemble(self.dE_dv) if slope > 0: raise firedrake.ConvergenceError( 'Minimization solver has invalid search direction. This is ' 'likely due to a negative thickness or friction coefficient or' 'otherwise physically invalid input data.') E_t = firedrake.replace(E, {u: u + t * v}) armijo = self.armijo contraction = self.contraction while self.problem.assemble(E_t) > E_0 + armijo * float(t) * slope: t.assign(t * contraction) u.assign(u + t * v) self.search_direction_solver.solve() self.iteration += 1
def solve(self): r"""Step the Newton iteration until convergence""" dE_dv = self.dE_dv S = self.problem.S _assemble = self.problem.assemble while abs(_assemble(dE_dv)) > self.tolerance * _assemble(S): self.step() if self.iteration >= self.max_iterations: raise firedrake.ConvergenceError( 'Newton search did not converge after {} iterations!'. format(self.max_iterations))
def solve(self, tolerance, max_iterations): r"""Run the iteration until the objective functional does not decrease to within tolerance""" objective = np.inf for iteration in range(max_iterations): if objective - self._objective <= tolerance * self._energy: return objective = self._objective self.step() raise firedrake.ConvergenceError( f"Gauss-Newton CG failed to converge after {max_iterations} steps!" )