def solve(self, var, b): timer = backend.Timer("Matrix-free solver") solver = backend.PETScKrylovSolver(*self.solver_parameters) solver.parameters.update(self.parameters) x = backend.Function(self.fn_space) if b.data is None: backend.info_red("Warning: got zero RHS for the solve associated with variable %s" % var) return adjlinalg.Vector(x) if isinstance(b.data, backend.Function): rhs = b.data.vector().copy() else: rhs = backend.assemble(b.data) if var.type in ['ADJ_TLM', 'ADJ_ADJOINT']: self.bcs = [backend.homogenize(bc) for bc in self.bcs if isinstance(bc, backend.cpp.DirichletBC)] + [bc for bc in self.bcs if not isinstance(bc, backend.DirichletBC)] for bc in self.bcs: bc.apply(rhs) if self.operators[1] is not None: # we have a user-supplied preconditioner solver.set_operators(self.data, self.operators[1]) solver.solve(backend.down_cast(x.vector()), backend.down_cast(rhs)) else: solver.solve(self.data, backend.down_cast(x.vector()), backend.down_cast(rhs)) timer.stop() return adjlinalg.Vector(x)
def solve(self, var, b): timer = backend.Timer("Matrix-free solver") solver = backend.PETScKrylovSolver(*self.solver_parameters) solver.parameters.update(self.parameters) x = backend.Function(self.fn_space) if b.data is None: backend.info_red( "Warning: got zero RHS for the solve associated with variable %s" % var) return adjlinalg.Vector(x) if isinstance(b.data, backend.Function): rhs = b.data.vector().copy() else: rhs = backend.assemble(b.data) if var.type in ['ADJ_TLM', 'ADJ_ADJOINT']: self.bcs = [ utils.homogenize(bc) for bc in self.bcs if isinstance(bc, backend.cpp.DirichletBC) ] + [ bc for bc in self.bcs if not isinstance(bc, backend.DirichletBC) ] for bc in self.bcs: bc.apply(rhs) if self.operators[ 1] is not None: # we have a user-supplied preconditioner solver.set_operators(self.data, self.operators[1]) solver.solve(backend.down_cast(x.vector()), backend.down_cast(rhs)) else: solver.solve(self.data, backend.down_cast(x.vector()), backend.down_cast(rhs)) timer.stop() return adjlinalg.Vector(x)
def down_cast(*args, **kwargs): """When a form is assembled, the information about its nonlinear dependencies is lost, and it is no longer easy to manipulate. Therefore, dolfin_adjoint overloads the :py:func:`dolfin.down_cast` function to *attach the form to the returned object*. This lets the automatic annotation work, even when the user calls the lower-level :py:data:`solve(A, x, b)`. """ dc = backend.down_cast(*args, **kwargs) if hasattr(args[0], 'form'): dc.form = args[0].form if hasattr(args[0], 'function'): dc.function = args[0].function if hasattr(args[0], 'bcs'): dc.bcs = args[0].bcs return dc