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 = [utils.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 = [utils.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 basic_solve(self, var, b):
        if isinstance(self.data, IdentityMatrix):
            x=b.duplicate()
            x.axpy(1.0, b)
            if isinstance(x.data, ufl.Form):
                x = Vector(backend.Function(x.fn_space, backend.assemble(x.data)))
        else:
            if var.type in ['ADJ_TLM', 'ADJ_ADJOINT', 'ADJ_SOA']:
                dirichlet_bcs = [utils.homogenize(bc) for bc in self.bcs if isinstance(bc, backend.DirichletBC)]
                other_bcs  = [bc for bc in self.bcs if not isinstance(bc, backend.DirichletBC)]
                bcs = dirichlet_bcs + other_bcs
            else:
                bcs = self.bcs

            test = self.test_function()

            #FIXME: This is a hack, the test and trial function should carry
            # the MultiMeshFunctionSpace as an attribute
            if hasattr(test, '_V_multi'):
                x = Vector(backend.MultiMeshFunction(test._V_multi))
            else:
                x = Vector(backend.Function(test.function_space()))

            #print "b.data is a %s in the solution of %s" % (b.data.__class__, var)
            if b.data is None and not hasattr(b, 'nonlinear_form'):
                # 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.
                backend.warning("Warning: got zero RHS for the solve associated with variable %s" % var)
            elif isinstance(b.data, backend.Function):

                assembled_lhs = self.assemble_data()
                [bc.apply(assembled_lhs) for bc in bcs]
                assembled_rhs = compatibility.assembled_rhs(b)
                [bc.apply(assembled_rhs) for bc in bcs]

                wrap_solve(assembled_lhs, x.data, assembled_rhs, self.solver_parameters)
            else:
                if hasattr(b, 'nonlinear_form'): # was a nonlinear solve
                    x = compatibility.assign_function_to_vector(x, b.nonlinear_u, function_space = test.function_space())
                    F = backend.replace(b.nonlinear_form, {b.nonlinear_u: x.data})
                    J = backend.replace(b.nonlinear_J, {b.nonlinear_u: x.data})
                    try:
                        compatibility.solve(F == 0, x.data, b.nonlinear_bcs, J=J, solver_parameters=self.solver_parameters)
                    except RuntimeError as rte:
                        x.data.vector()[:] = float("nan")

                else:
                    assembled_lhs = self.assemble_data()
                    [bc.apply(assembled_lhs) for bc in bcs]
                    assembled_rhs = wrap_assemble(b.data, test)
                    [bc.apply(assembled_rhs) for bc in bcs]

                    wrap_solve(assembled_lhs, x.data, assembled_rhs, self.solver_parameters)

        return x
Beispiel #3
0
    def diag_assembly_cb(dependencies, values, hermitian, coefficient, context):
        """This callback must conform to the libadjoint Python block assembly
        interface. It returns either the form or its transpose, depending on
        the value of the logical hermitian."""

        assert coefficient == 1

        value_coeffs = [v.data for v in values]
        expressions.update_expressions(frozen_expressions)
        constant.update_constants(frozen_constants)
        eq_l = backend.replace(eq_lhs, dict(zip(diag_coeffs, value_coeffs)))

        kwargs = {"cache": eq_l in caching.assembled_fwd_forms}  # should we cache our matrices on the way backwards?

        if hermitian:
            # Homogenise the adjoint boundary conditions. This creates the adjoint
            # solution associated with the lifted discrete system that is actually solved.
            adjoint_bcs = [utils.homogenize(bc) for bc in eq_bcs if isinstance(bc, backend.DirichletBC)] + [
                bc for bc in eq_bcs if not isinstance(bc, backend.DirichletBC)
            ]
            if len(adjoint_bcs) == 0:
                adjoint_bcs = None
            else:
                adjoint_bcs = misc.uniq(adjoint_bcs)

            kwargs["bcs"] = adjoint_bcs
            kwargs["solver_parameters"] = solver_parameters
            kwargs["adjoint"] = True

            if initial_guess:
                kwargs["initial_guess"] = value_coeffs[dependencies.index(initial_guess_var)]

            if replace_map:
                kwargs["replace_map"] = dict(zip(diag_coeffs, value_coeffs))

            return (
                matrix_class(
                    backend.adjoint(eq_l, reordered_arguments=ufl.algorithms.extract_arguments(eq_l)), **kwargs
                ),
                adjlinalg.Vector(None, fn_space=u.function_space()),
            )
        else:

            kwargs["bcs"] = misc.uniq(eq_bcs)
            kwargs["solver_parameters"] = solver_parameters
            kwargs["adjoint"] = False

            if initial_guess:
                kwargs["initial_guess"] = value_coeffs[dependencies.index(initial_guess_var)]

            if replace_map:
                kwargs["replace_map"] = dict(zip(diag_coeffs, value_coeffs))

            return (matrix_class(eq_l, **kwargs), adjlinalg.Vector(None, fn_space=u.function_space()))
    def caching_solve(self, var, b):
        if isinstance(self.data, IdentityMatrix):
            output = b.duplicate()
            output.axpy(1.0, b)
            if isinstance(output.data, ufl.Form):
                output = Vector(backend.Function(output.fn_space, backend.assemble(output.data)))
        elif b.data is None:
            backend.warning("Warning: got zero RHS for the solve associated with variable %s" % var)
            output = Vector(backend.Function(self.test_function().function_space()))
        else:
            dirichlet_bcs = [utils.homogenize(bc) for bc in self.bcs if isinstance(bc, backend.DirichletBC)]
            other_bcs  = [bc for bc in self.bcs if not isinstance(bc, backend.DirichletBC)]
            bcs = dirichlet_bcs + other_bcs

            output = Vector(backend.Function(self.test_function().function_space()))
            #print "b.data is a %s in the solution of %s" % (b.data.__class__, var)
            if backend.parameters["adjoint"]["symmetric_bcs"] and backend.__version__ > '1.2.0':
                assembler = backend.SystemAssembler(self.data, b.data, bcs)
                assembled_rhs = backend.Vector()
                assembler.assemble(assembled_rhs)
            elif isinstance(b.data, ufl.Form):
                assembled_rhs = wrap_assemble(b.data, self.test_function())
            else:
                if backend.__name__ == "dolfin":
                    assembled_rhs = b.data.vector()
                else:
                    assembled_rhs = b.data
            [bc.apply(assembled_rhs) for bc in bcs]

            if not var in caching.lu_solvers:
                if backend.parameters["adjoint"]["debug_cache"]:
                    backend.info_red("Got a cache miss for %s" % var)

                if backend.parameters["adjoint"]["symmetric_bcs"] and backend.__version__ > '1.2.0':
                    assembled_lhs = backend.Matrix()
                    assembler.assemble(assembled_lhs)
                else:
                    assembled_lhs = self.assemble_data()
                    [bc.apply(assembled_lhs) for bc in bcs]

                caching.lu_solvers[var] = compatibility.LUSolver(assembled_lhs, "mumps")
                caching.lu_solvers[var].parameters["reuse_factorization"] = True
            else:
                if backend.parameters["adjoint"]["debug_cache"]:
                    backend.info_green("Got a cache hit for %s" % var)

            caching.lu_solvers[var].solve(output.data.vector(), assembled_rhs)

        return output
Beispiel #5
0
 def pixel_to_ray_vec(self, pts):
     """ given a pixel, calculate a line that all points will be projected to the pixel
     through the camera
     Params:
         pts - 2 by n array, points in image coordinates
     Return:
         d - 3 by n array, direction vector for each pixel
         C - 3 by 1 array, camera center in world frame, pencil of point representation.
     """
     pts_homo = homogenize(pts)
     pts_norm = np.matmul(self.K_inv, pts_homo)
     d = np.matmul(self.R.T, pts_norm)
     d = d / np.sign(d[0, :]) / np.linalg.norm(d, axis=0)
     C = self.C_world_inhomo
     return d, C
Beispiel #6
0
        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 = [utils.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
Beispiel #7
0
    def derivative_assembly(self, dependencies, values, variable, hermitian):
        replace_map = {}

        for i in range(len(self.deps)):
            if self.deps[i] == self.ic_var: continue
            j = dependencies.index(self.deps[i])
            replace_map[self.coeffs[i]] = values[j].data

        diff_var = values[dependencies.index(variable)].data

        current_form = backend.replace(self.form, replace_map)
        deriv = backend.derivative(current_form, diff_var)

        if hermitian:
            deriv = backend.adjoint(deriv)
            bcs = [utils.homogenize(bc) for bc in self.bcs if isinstance(bc, backend.DirichletBC)] + [bc for bc in self.bcs if not isinstance(bc, backend.DirichletBC)]
        else:
            bcs = self.bcs

        return adjlinalg.Matrix(deriv, bcs=bcs)
                def solve(selfmat, var, b):
                    if selfmat.adjoint:
                        operators = transpose_operators(selfmat.operators)
                    else:
                        operators = selfmat.operators

                    # Fetch/construct the solver
                    if var.type in ['ADJ_FORWARD', 'ADJ_TLM']:
                        solver = petsc_krylov_solvers[idx]
                        need_to_set_operator = self._need_to_reset_operator
                    else:
                        if adj_petsc_krylov_solvers[idx] is None:
                            need_to_set_operator = True
                            adj_petsc_krylov_solvers[idx] = PETScKrylovSolver(*solver_parameters)
                            adj_ksp = adj_petsc_krylov_solvers[idx].ksp()
                            fwd_ksp = petsc_krylov_solvers[idx].ksp()
                            adj_ksp.setOptionsPrefix(fwd_ksp.getOptionsPrefix())
                            adj_ksp.setType(fwd_ksp.getType())
                            adj_ksp.pc.setType(fwd_ksp.pc.getType())
                            adj_ksp.setFromOptions()
                        else:
                            need_to_set_operator = self._need_to_reset_operator
                        solver = adj_petsc_krylov_solvers[idx]
                        # FIXME: work around DOLFIN bug #583
                        try:
                            solver.parameters.convergence_norm_type
                        except:
                            solver.parameters.convergence_norm_type = "preconditioned"
                        # end FIXME
                    solver.parameters.update(parameters)
                    self._need_to_reset_operator = False

                    if selfmat.adjoint:
                        (nsp_, tnsp_) = (tnsp, nsp)
                    else:
                        (nsp_, tnsp_) = (nsp, tnsp)

                    x = dolfin.Function(fn_space)
                    if selfmat.initial_guess is not None and var.type == 'ADJ_FORWARD':
                        x.vector()[:] = selfmat.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']:
                        selfmat.bcs = [utils.homogenize(bc) for bc in selfmat.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in selfmat.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 selfmat.bcs]

                        if need_to_set_operator:
                            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, selfmat.bcs)
                                if has_preconditioner:
                                    (P, rhstmp) = dolfin.assemble_system(operators[1], dolfin.inner(b.data, v)*dolfin.dx, selfmat.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 selfmat.bcs]
                                if has_preconditioner:
                                    P = dolfin.assemble(operators[1])
                                    [bc.apply(P) for bc in selfmat.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, selfmat.bcs)
                            if need_to_set_operator:
                                if has_preconditioner:
                                    (P, rhstmp) = dolfin.assemble_system(operators[1], b.data, selfmat.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 selfmat.bcs]
                            [bc.apply(rhs) for bc in selfmat.bcs]
                            if need_to_set_operator:
                                if has_preconditioner:
                                    P = dolfin.assemble(operators[1])
                                    [bc.apply(P) for bc in selfmat.bcs]
                                    solver.set_operators(A, P)
                                else:
                                    solver.set_operator(A)

                    if need_to_set_operator:
                        print "|A|: %.6e" % A.norm("frobenius")

                    # Set the nullspace for the linear operator
                    if nsp_ is not None and need_to_set_operator:
                        dolfin.as_backend_type(A).set_nullspace(nsp_)

                    # (Possibly override the user in) orthogonalize
                    # the right-hand-side
                    if tnsp_ is not None:
                        tnsp_.orthogonalize(rhs)

                    print "%s: |b|: %.6e" % (var, rhs.norm("l2"))
                    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)

                    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 = [utils.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]

                            # Set nullspace
                            if nsp:
                                dolfin.as_backend_type(A).set_nullspace(nsp)
                                nsp.orthogonalize(b);

                            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]

                            # Set nullspace
                            if nsp:
                                dolfin.as_backend_type(A).set_nullspace(nsp)
                                nsp.orthogonalize(rhs);

                            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)
                def solve(self, var, b):
                    if self.adjoint:
                        operators = transpose_operators(self.operators)
                    else:
                        operators = self.operators

                    # Fetch/construct the solver
                    if var.type in ['ADJ_FORWARD', 'ADJ_TLM']:
                        solver = krylov_solvers[idx]
                        need_to_set_operator = False
                    else:
                        if adj_krylov_solvers[idx] is None:
                            need_to_set_operator = True
                            adj_krylov_solvers[idx] = KrylovSolver(*solver_parameters)
                        else:
                            need_to_set_operator = False
                        solver = adj_krylov_solvers[idx]
                    solver.parameters.update(parameters)

                    if self.adjoint:
                        (nsp_, tnsp_) = (tnsp, nsp)
                    else:
                        (nsp_, tnsp_) = (nsp, 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 = [utils.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 need_to_set_operator:
                            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 need_to_set_operator:
                                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 need_to_set_operator:
                                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)

                    # Set the nullspace for the linear operator
                    if nsp_ is not None and need_to_set_operator:
                        dolfin.as_backend_type(A).set_nullspace(nsp_)

                    # (Possibly override the user in) orthogonalize
                    # the right-hand-side
                    if tnsp_ is not None:
                        tnsp_.orthogonalize(rhs)

                    solver.solve(x.vector(), rhs)
                    return adjlinalg.Vector(x)
Beispiel #11
0
 def get_image_coordinate(self, X):
     """ get the image coordinate of world point X """
     x_homo = np.matmul(self.P, homogenize(X))
     x = dehomogenize(x_homo)
     return x