def transpose_operators(operators): out = [None, None] for i in range(2): op = operators[i] if op is None: out[i] = None elif isinstance(op, dolfin.cpp.GenericMatrix): out[i] = op.__class__() dolfin.assemble(dolfin.adjoint(op.form), tensor=out[i]) if hasattr(op, 'bcs'): adjoint_bcs = [dolfin.homogenize(bc) for bc in op.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in op.bcs if not isinstance(bc, dolfin.DirichletBC)] [bc.apply(out[i]) for bc in adjoint_bcs] elif isinstance(op, dolfin.Form) or isinstance(op, ufl.form.Form): out[i] = dolfin.adjoint(op) if hasattr(op, 'bcs'): out[i].bcs = [dolfin.homogenize(bc) for bc in op.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in op.bcs if not isinstance(bc, dolfin.DirichletBC)] elif isinstance(op, AdjointKrylovMatrix): pass else: print "op.__class__: ", op.__class__ raise libadjoint.exceptions.LibadjointErrorNotImplemented("Don't know how to transpose anything else!") return out
def solve(self, var, b): if reuse_factorization is False: return adjlinalg.Matrix.solve(self, var, b) if var.type in ['ADJ_TLM', 'ADJ_ADJOINT']: bcs = [dolfin.homogenize(bc) for bc in self.bcs if isinstance(bc, dolfin.DirichletBC)] + [bc for bc in self.bcs if not isinstance(bc, dolfin.DirichletBC)] else: bcs = self.bcs if var.type in ['ADJ_FORWARD', 'ADJ_TLM']: solver = lu_solvers[idx] if solver is None: A = assembly.assemble(self.data); [bc.apply(A) for bc in bcs] lu_solvers[idx] = LUSolver(A) lu_solvers[idx].parameters["reuse_factorization"] = True solver = lu_solvers[idx] else: if adj_lu_solvers[idx] is None: A = assembly.assemble(self.data); [bc.apply(A) for bc in bcs] adj_lu_solvers[idx] = LUSolver(A) adj_lu_solvers[idx].parameters["reuse_factorization"] = True solver = adj_lu_solvers[idx] x = adjlinalg.Vector(dolfin.Function(self.test_function().function_space())) if b.data is None: # This means we didn't get any contribution on the RHS of the adjoint system. This could be that the # simulation ran further ahead than when the functional was evaluated, or it could be that the # functional is set up incorrectly. dolfin.info_red("Warning: got zero RHS for the solve associated with variable %s" % var) else: if isinstance(b.data, dolfin.Function): b_vec = b.data.vector().copy() else: b_vec = dolfin.assemble(b.data) [bc.apply(b_vec) for bc in bcs] solver.solve(x.data.vector(), b_vec, annotate=False) return x
v1, v2 = df.split(v) # Initial Guesses u1_i = df.Expression("x[0]") u2_i = df.Expression("1-x[0]") # Impose boundary conditions for the solution to the nonlinear system bc = [ df.DirichletBC(V2.sub(0), df.Constant(0.0), left_boundary), df.DirichletBC(V2.sub(0), df.Constant(1.0), right_boundary), df.DirichletBC(V2.sub(1), df.Constant(1.0), left_boundary), df.DirichletBC(V2.sub(1), df.Constant(0.0), right_boundary) ] # Make homogeneous version of BCs for the update bch = df.homogenize(bc) # Set the initial guess u.interpolate(df.Expression(("u1_i", "u2_i"), u1_i=u1_i, u2_i=u2_i)) # Allocate Newton update function u_inc = df.Function(V2) # Extract grid points xg = mesh.coordinates() # Nonlinear coefficient 1 q1 = ufl.operators.exp(a * u1) # Nonlinear coefficient 2 q2 = ufl.operators.exp(a * u2)
v1, v2 = df.split(v) # Initial Guesses u1_i = df.Expression("x[0]") u2_i = df.Expression("1-x[0]") # Impose boundary conditions for the solution to the nonlinear system bc = [ df.DirichletBC(V2.sub(0), df.Constant(0.0), left_boundary), df.DirichletBC(V2.sub(0), df.Constant(1.0), right_boundary), df.DirichletBC(V2.sub(1), df.Constant(1.0), left_boundary), df.DirichletBC(V2.sub(1), df.Constant(0.0), right_boundary), ] # Make homogeneous version of BCs for the update bch = df.homogenize(bc) # Set the initial guess u.interpolate(df.Expression(("u1_i", "u2_i"), u1_i=u1_i, u2_i=u2_i)) # Allocate Newton update function u_inc = df.Function(V2) # Extract grid points xg = mesh.coordinates() # Nonlinear coefficient 1 q1 = ufl.operators.exp(a * u1) # Nonlinear coefficient 2 q2 = ufl.operators.exp(a * u2)
def solve(self, var, b): if self.adjoint: operators = transpose_operators(self.operators) else: operators = self.operators solver = dolfin.KrylovSolver(*solver_parameters) solver.parameters.update(parameters) if self.adjoint: # swap nullspaces (nsp_, tnsp_) = (tnsp, nsp) else: (nsp_, tnsp_) = (nsp, tnsp) if nsp_ is not None: solver.set_nullspace(nsp_) if tnsp_ is not None and hasattr(solver, 'set_transpose_nullspace'): solver.set_transpose_nullspace(tnsp_) x = dolfin.Function(fn_space) if self.initial_guess is not None and var.type == 'ADJ_FORWARD': x.vector()[:] = self.initial_guess.vector() if b.data is None: dolfin.info_red("Warning: got zero RHS for the solve associated with variable %s" % var) return adjlinalg.Vector(x) if var.type in ['ADJ_TLM', 'ADJ_ADJOINT']: self.bcs = [dolfin.homogenize(bc) for bc in self.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in self.bcs if not isinstance(bc, dolfin.cpp.DirichletBC)] # This is really hideous. Sorry. if isinstance(b.data, dolfin.Function): rhs = b.data.vector().copy() [bc.apply(rhs) for bc in self.bcs] if assemble_system: # if we called assemble_system, rather than assemble v = dolfin.TestFunction(fn_space) (A, rhstmp) = dolfin.assemble_system(operators[0], dolfin.inner(b.data, v)*dolfin.dx, self.bcs) if has_preconditioner: (P, rhstmp) = dolfin.assemble_system(operators[1], dolfin.inner(b.data, v)*dolfin.dx, self.bcs) solver.set_operators(A, P) else: solver.set_operator(A) else: # we called assemble A = dolfin.assemble(operators[0]) [bc.apply(A) for bc in self.bcs] if has_preconditioner: P = dolfin.assemble(operators[1]) [bc.apply(P) for bc in self.bcs] solver.set_operators(A, P) else: solver.set_operator(A) else: if assemble_system: # if we called assemble_system, rather than assemble (A, rhs) = dolfin.assemble_system(operators[0], b.data, self.bcs) if has_preconditioner: (P, rhstmp) = dolfin.assemble_system(operators[1], b.data, self.bcs) solver.set_operators(A, P) else: solver.set_operator(A) else: # we called assemble A = dolfin.assemble(operators[0]) rhs = dolfin.assemble(b.data) [bc.apply(A) for bc in self.bcs] [bc.apply(rhs) for bc in self.bcs] if has_preconditioner: P = dolfin.assemble(operators[1]) [bc.apply(P) for bc in self.bcs] solver.set_operators(A, P) else: solver.set_operator(A) if tnsp_ is not None: tnsp_.orthogonalize(rhs) solver.solve(x.vector(), rhs) return adjlinalg.Vector(x)
def solve(self, var, b): if self.adjoint: operators = transpose_operators(self.operators) else: operators = self.operators solver = dolfin.LinearSolver(*solver_parameters) solver.parameters.update(parameters) if nsp is not None and self.adjoint is False: solver.set_nullspace(nsp) if nsp is not None and self.adjoint: # maybe add a LinearSolver.set_adjoint_nullspace? dolfin.info_red("Warning: setting nullspace for adjoint solve to be the same for the forward solve. May not be the actual basis for the nullspace.") solver.set_nullspace(nsp) x = dolfin.Function(fn_space) if self.initial_guess is not None and var.type == 'ADJ_FORWARD': x.vector()[:] = self.initial_guess.vector() if b.data is None: dolfin.info_red("Warning: got zero RHS for the solve associated with variable %s" % var) return adjlinalg.Vector(x) if var.type in ['ADJ_TLM', 'ADJ_ADJOINT']: self.bcs = [dolfin.homogenize(bc) for bc in self.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in self.bcs if not isinstance(bc, dolfin.cpp.DirichletBC)] # This is really hideous. Sorry. if isinstance(b.data, dolfin.Function): rhs = b.data.vector().copy() [bc.apply(rhs) for bc in self.bcs] if assemble_system: # if we called assemble_system, rather than assemble v = dolfin.TestFunction(fn_space) (A, rhstmp) = dolfin.assemble_system(operators[0], dolfin.inner(b.data, v)*dolfin.dx, self.bcs) if has_preconditioner: (P, rhstmp) = dolfin.assemble_system(operators[1], dolfin.inner(b.data, v)*dolfin.dx, self.bcs) solver.set_operators(A, P) else: solver.set_operator(A) else: # we called assemble A = dolfin.assemble(operators[0]) [bc.apply(A) for bc in self.bcs] if has_preconditioner: P = dolfin.assemble(operators[1]) [bc.apply(P) for bc in self.bcs] solver.set_operators(A, P) else: solver.set_operator(A) else: if assemble_system: # if we called assemble_system, rather than assemble (A, rhs) = dolfin.assemble_system(operators[0], b.data, self.bcs) if has_preconditioner: (P, rhstmp) = dolfin.assemble_system(operators[1], b.data, self.bcs) solver.set_operators(A, P) else: solver.set_operator(A) else: # we called assemble A = dolfin.assemble(operators[0]) rhs = dolfin.assemble(b.data) [bc.apply(A) for bc in self.bcs] [bc.apply(rhs) for bc in self.bcs] if has_preconditioner: P = dolfin.assemble(operators[1]) [bc.apply(P) for bc in self.bcs] solver.set_operators(A, P) else: solver.set_operator(A) solver.solve(x.vector(), rhs) return adjlinalg.Vector(x)