예제 #1
0
def taylor_test_expression(exp, V, seed=None):
    """
    Performs a Taylor test of an Expression with dependencies.

    exp: The expression to test
    V: A suitable function space on which the expression will be projected.
    seed: The initial perturbation coefficient for the taylor test.

    Warning: This function resets the adjoint tape! """
    from . import drivers, functional, projection
    from .controls import Control

    adjglobals.adj_reset()

    # Annotate test model
    s = projection.project(exp, V, annotate=True)
    mesh = V.mesh()

    Jform = s**2*backend.dx + exp*backend.dx(domain=mesh)

    J = functional.Functional(Jform)
    J0 = backend.assemble(Jform)

    controls = [Control(c) for c in exp.dependencies]
    dJd0 = drivers.compute_gradient(J, controls, forget=False)

    for i in range(len(controls)):
        def Jfunc(new_val):
            dep = exp.dependencies[i]

            # Remember the old dependency value for later
            old_val = float(dep)

            # Compute the functional value
            dep.assign(new_val)
            s = projection.project(exp, V, annotate=False)
            out = backend.assemble(s**2*backend.dx + exp*backend.dx(domain=mesh))

            # Restore the old dependency value
            dep.assign(old_val)

            return out

        #HJ = hessian(J, controls[i], warn=False)
        #minconv = taylor_test(Jfunc, controls[i], J0, dJd0[i], HJm=HJ)
        minconv = taylor_test(Jfunc, controls[i], J0, dJd0[i], seed=seed)

        if math.isnan(minconv):
            warning("Convergence order is not a number. Assuming that you \
have a linear or constant constraint dependency (e.g. check that the Taylor \
remainder are all 0).")
        else:
            if not minconv > 1.9:
                raise Exception("The Taylor test failed when checking the \
derivative with respect to the %i'th dependency." % (i+1))

    adjglobals.adj_reset()
예제 #2
0
def project_dolfin(v, V=None, bcs=None, mesh=None, solver_type="cg", preconditioner_type="default", form_compiler_parameters=None, annotate=None, name=None):
    '''The project call performs an equation solve, and so it too must be annotated so that the
    adjoint and tangent linear models may be constructed automatically by libadjoint.

    To disable the annotation of this function, just pass :py:data:`annotate=False`. This is useful in
    cases where the solve is known to be irrelevant or diagnostic for the purposes of the adjoint
    computation (such as projecting fields to other function spaces for the purposes of
    visualisation).'''

    to_annotate = utils.to_annotate(annotate)

    if isinstance(v, backend.Expression) and (annotate is not True):
        to_annotate = False

    if isinstance(v, backend.Constant) and (annotate is not True):
        to_annotate = False

    out = backend.project(v=v, V=V, bcs=bcs, mesh=mesh, solver_type=solver_type, preconditioner_type=preconditioner_type, form_compiler_parameters=form_compiler_parameters)
    out = utils.function_to_da_function(out)

    if name is not None:
        out.adj_name = name
        out.rename(name, "a Function from dolfin-adjoint")

    if to_annotate:
        # reproduce the logic from project. This probably isn't future-safe, but anyway

        if V is None:
            V = backend.fem.projection._extract_function_space(v, mesh)
        if mesh is None:
            mesh = V.mesh()

        # Define variational problem for projection
        w = backend.TestFunction(V)
        Pv = backend.TrialFunction(V)
        a = backend.inner(w, Pv)*backend.dx(domain=mesh)
        L = backend.inner(w, v)*backend.dx(domain=mesh)

        solving.annotate(a == L, out, bcs, solver_parameters={"linear_solver": solver_type, "preconditioner": preconditioner_type, "symmetric": True})

        if backend.parameters["adjoint"]["record_all"]:
            adjglobals.adjointer.record_variable(adjglobals.adj_variables[out], libadjoint.MemoryStorage(adjlinalg.Vector(out)))

    return out
예제 #3
0
def taylor_test_expression(exp, V):
    """
    Performs a Taylor test of an Expression with dependencies.

    exp: The expression to test
    V: A suitable function space on which the expression will be projected.

    Warning: This function resets the adjoint tape! """

    adjglobals.adj_reset()

    # Annotate test model
    s = projection.project(exp, V, annotate=True)
    mesh = V.mesh()

    Jform = s**2*backend.dx + exp*backend.dx(domain=mesh)

    J = functional.Functional(Jform)
    J0 = backend.assemble(Jform)

    deps = exp.dependencies()
    controls = [Control(c) for c in deps]
    dJd0 = drivers.compute_gradient(J, controls, forget=False)

    for i in range(len(controls)):
        def Jfunc(new_val):
            dep = exp.dependencies()[i]

            # Remember the old dependency value for later
            old_val = float(dep)

            # Compute the functional value
            dep.assign(new_val)
            s = projection.project(exp, V, annotate=False)
            out = backend.assemble(s**2*backend.dx + exp*backend.dx(domain=mesh))

            # Restore the old dependency value
            dep.assign(old_val)

            return out

        #HJ = hessian(J, controls[i], warn=False)
        #minconv = taylor_test(Jfunc, controls[i], J0, dJd0[i], HJm=HJ)
        minconv = taylor_test(Jfunc, controls[i], J0, dJd0[i])

        if math.isnan(minconv):
            warning("Convergence order is not a number. Assuming that you \
have a linear or constant constraint dependency (e.g. check that the Taylor \
remainder are all 0).")
        else:
            if not minconv > 1.9:
                raise Exception, "The Taylor test failed when checking the \
derivative with respect to the %i'th dependency." % (i+1)

    adjglobals.adj_reset()
예제 #4
0
    def __init__(self, v, V, output, bcs=[], *args, **kwargs):
        mesh = kwargs.pop("mesh", None)
        if mesh is None:
            mesh = V.mesh()
        dx = backend.dx(mesh)
        w = backend.TestFunction(V)
        Pv = backend.TrialFunction(V)
        a = backend.inner(w, Pv) * dx
        L = backend.inner(w, v) * dx

        super(ProjectBlock, self).__init__(a == L, output, bcs, *args,
                                           **kwargs)
예제 #5
0
        def Jfunc(new_val):
            dep = exp.dependencies()[i]

            # Remember the old dependency value for later
            old_val = float(dep)

            # Compute the functional value
            dep.assign(new_val)
            s = projection.project(exp, V, annotate=False)
            out = backend.assemble(s**2*backend.dx + exp*backend.dx(domain=mesh))

            # Restore the old dependency value
            dep.assign(old_val)

            return out
예제 #6
0
        def Jfunc(new_val):
            dep = exp.dependencies[i]

            # Remember the old dependency value for later
            old_val = float(dep)

            # Compute the functional value
            dep.assign(new_val)
            s = projection.project(exp, V, annotate=False)
            out = backend.assemble(s**2*backend.dx + exp*backend.dx(domain=mesh))

            # Restore the old dependency value
            dep.assign(old_val)

            return out
예제 #7
0
def project_dolfin(v,
                   V=None,
                   bcs=None,
                   mesh=None,
                   solver_type="lu",
                   preconditioner_type="default",
                   form_compiler_parameters=None,
                   annotate=None,
                   name=None):
    '''The project call performs an equation solve, and so it too must be annotated so that the
    adjoint and tangent linear models may be constructed automatically by libadjoint.

    To disable the annotation of this function, just pass :py:data:`annotate=False`. This is useful in
    cases where the solve is known to be irrelevant or diagnostic for the purposes of the adjoint
    computation (such as projecting fields to other function spaces for the purposes of
    visualisation).'''

    to_annotate = utils.to_annotate(annotate)

    if isinstance(v, backend.Expression) and (annotate is not True):
        to_annotate = False

    if isinstance(v, backend.Constant) and (annotate is not True):
        to_annotate = False

    out = backend.project(v=v,
                          V=V,
                          bcs=bcs,
                          mesh=mesh,
                          solver_type=solver_type,
                          preconditioner_type=preconditioner_type,
                          form_compiler_parameters=form_compiler_parameters)
    out = utils.function_to_da_function(out)

    if name is not None:
        out.adj_name = name
        out.rename(name, "a Function from dolfin-adjoint")

    if to_annotate:
        # reproduce the logic from project. This probably isn't future-safe, but anyway

        if V is None:
            V = backend.fem.projection._extract_function_space(v, mesh)
        if mesh is None:
            mesh = V.mesh()

        # Define variational problem for projection
        w = backend.TestFunction(V)
        Pv = backend.TrialFunction(V)
        a = backend.inner(w, Pv) * backend.dx(domain=mesh)
        L = backend.inner(w, v) * backend.dx(domain=mesh)

        solving.annotate(a == L,
                         out,
                         bcs,
                         solver_parameters={
                             "linear_solver": solver_type,
                             "preconditioner": preconditioner_type,
                             "symmetric": True
                         })

        if backend.parameters["adjoint"]["record_all"]:
            adjglobals.adjointer.record_variable(
                adjglobals.adj_variables[out],
                libadjoint.MemoryStorage(adjlinalg.Vector(out)))

    return out