コード例 #1
0
def test_supermesh_project_hessian(vector):
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    source, target_space = supermesh_setup()
    control = Control(source)
    target = project(source, target_space)
    J = assemble(inner(target, target)**2 * dx)
    rf = ReducedFunctional(J, control)

    source_space = source.function_space()
    h = Function(source_space)
    h.vector()[:] = 10 * rand(source_space.dim())

    J.block_variable.adj_value = 1.0
    source.block_variable.tlm_value = h

    tape = get_working_tape()
    tape.evaluate_adj()
    tape.evaluate_tlm()

    J.block_variable.hessian_value = 0.0

    tape.evaluate_hessian()

    dJdm = J.block_variable.tlm_value
    assert isinstance(source.block_variable.adj_value, Vector)
    assert isinstance(source.block_variable.hessian_value, Vector)
    Hm = source.block_variable.hessian_value.inner(h.vector())
    assert taylor_test(rf, source, h, dJdm=dJdm, Hm=Hm) > 2.9
コード例 #2
0
def test_interpolate_tlm_wit_constant():
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    mesh = IntervalMesh(10, 0, 1)
    V1 = FunctionSpace(mesh, "CG", 2)
    V2 = FunctionSpace(mesh, "DG", 1)

    x = SpatialCoordinate(mesh)
    f = interpolate(x[0], V1)
    g = interpolate(sin(x[0]), V1)
    c = Constant(5.0)
    u = Function(V2)
    u.interpolate(c * f**2)

    # test tlm w.r.t constant only:
    c.block_variable.tlm_value = Constant(1.0)
    J = assemble(u**2 * dx)
    rf = ReducedFunctional(J, Control(c))
    h = Constant(1.0)

    tape = get_working_tape()
    tape.evaluate_tlm()
    assert abs(J.block_variable.tlm_value - 2.0) < 1e-5
    assert taylor_test(rf, c, h, dJdm=J.block_variable.tlm_value) > 1.9

    # test tlm w.r.t constant c and function f:
    tape.reset_tlm_values()
    c.block_variable.tlm_value = Constant(0.4)
    f.block_variable.tlm_value = g
    rf(c)  # replay to reset checkpoint values based on c=5
    tape.evaluate_tlm()
    assert abs(J.block_variable.tlm_value -
               (0.8 + 100. * (5 * cos(1.) - 3 * sin(1.)))) < 1e-4
コード例 #3
0
def test_interpolate_tlm():
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    mesh = UnitSquareMesh(10, 10)
    V1 = VectorFunctionSpace(mesh, "CG", 1)
    V2 = VectorFunctionSpace(mesh, "DG", 0)
    V3 = VectorFunctionSpace(mesh, "CG", 2)

    x = SpatialCoordinate(mesh)
    f = interpolate(as_vector((x[0] * x[1], x[0] + x[1])), V1)
    g = interpolate(as_vector((sin(x[1]) + x[0], cos(x[0]) * x[1])), V2)
    u = Function(V3)

    u.interpolate(f - 0.5 * g + f / (1 + dot(f, g)))
    J = assemble(inner(f, g) * u**2 * dx)
    rf = ReducedFunctional(J, Control(f))

    h = Function(V1)
    h.vector()[:] = 1
    f.block_variable.tlm_value = h

    tape = get_working_tape()
    tape.evaluate_tlm()

    assert J.block_variable.tlm_value is not None
    assert taylor_test(rf, f, h, dJdm=J.block_variable.tlm_value) > 1.9
コード例 #4
0
def test_interpolate_hessian_nonlinear_expr_multi():
    # Note this is a direct copy of
    # pyadjoint/tests/firedrake_adjoint/test_hessian.py::test_nonlinear
    # with modifications where indicated.

    from firedrake_adjoint import ReducedFunctional, Control, taylor_test, get_working_tape

    # Get tape instead of creating a new one for consistency with other tests
    tape = get_working_tape()

    mesh = UnitSquareMesh(10, 10)
    V = FunctionSpace(mesh, "Lagrange", 1)

    # Interpolate from f in another function space to force hessian evaluation
    # of interpolation. Functions in W form our control space c, our expansion
    # space h and perterbation direction g.
    W = FunctionSpace(mesh, "Lagrange", 2)
    f = Function(W)
    f.vector()[:] = 5
    w = Function(W)
    w.vector()[:] = 4
    c = Constant(2.)
    # Note that we interpolate from a nonlinear expression with 3 coefficients
    expr_interped = Function(V).interpolate(f**2 + w**2 + c**2)

    u = Function(V)
    v = TestFunction(V)
    bc = DirichletBC(V, Constant(1), "on_boundary")

    F = inner(grad(u), grad(v)) * dx - u**2 * v * dx - expr_interped * v * dx
    solve(F == 0, u, bc)

    J = assemble(u**4 * dx)
    Jhat = ReducedFunctional(J, Control(f))

    # Note functions are in W, not V.
    h = Function(W)
    h.vector()[:] = 10 * rand(W.dim())

    J.block_variable.adj_value = 1.0
    # Note only the tlm_value of f is set here - unclear why.
    f.block_variable.tlm_value = h

    tape.evaluate_adj()
    tape.evaluate_tlm()

    J.block_variable.hessian_value = 0

    tape.evaluate_hessian()

    g = f.copy(deepcopy=True)

    dJdm = J.block_variable.tlm_value
    assert isinstance(f.block_variable.adj_value, Vector)
    assert isinstance(f.block_variable.hessian_value, Vector)
    Hm = f.block_variable.hessian_value.inner(h.vector())
    # If the new interpolate block has the right hessian, taylor test
    # convergence rate should be as for the unmodified test.
    assert taylor_test(Jhat, g, h, dJdm=dJdm, Hm=Hm) > 2.9
コード例 #5
0
def test_init_constant():
    from firedrake_adjoint import ReducedFunctional, Control
    mesh = UnitSquareMesh(1, 1)
    c1 = Constant(1.0)
    c2 = Constant(c1)
    J = assemble(c2 * dx(domain=mesh))
    rf = ReducedFunctional(J, Control(c1))
    assert np.isclose(rf(-1.0), -1.0)
コード例 #6
0
def test_copy_function():
    from firedrake_adjoint import ReducedFunctional, Control
    mesh = UnitSquareMesh(1, 1)
    V = FunctionSpace(mesh, "CG", 1)
    one = Constant(1.0)
    f = interpolate(one, V)
    g = f.copy(deepcopy=True)
    J = assemble(g * dx)
    rf = ReducedFunctional(J, Control(f))
    assert np.isclose(rf(interpolate(-one, V)), -J)
コード例 #7
0
def test_interpolate_constant():
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    mesh = UnitSquareMesh(10, 10)
    V1 = FunctionSpace(mesh, "CG", 1)

    c = Constant(1.0, domain=mesh)
    u = interpolate(c, V1)

    J = assemble(u**2 * dx)
    rf = ReducedFunctional(J, Control(c))

    h = Constant(0.1, domain=mesh)
    assert taylor_test(rf, c, h) > 1.9
コード例 #8
0
def test_self_interpolate():
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    mesh = UnitSquareMesh(1, 1)
    V = FunctionSpace(mesh, "CG", 1)
    u = Function(V)

    c = Constant(1.)
    u.interpolate(u + c)

    J = assemble(u**2 * dx)
    rf = ReducedFunctional(J, Control(c))

    h = Constant(0.1)
    assert taylor_test(rf, c, h) > 1.9
コード例 #9
0
def test_supermesh_project_gradient(vector):
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    source, target_space = supermesh_setup()
    source_space = source.function_space()
    control = Control(source)
    target = project(source, target_space)
    J = assemble(inner(target, target) * dx)
    rf = ReducedFunctional(J, control)

    # Taylor test
    h = Function(source_space)
    h.vector()[:] = rand(source_space.dim())
    minconv = taylor_test(rf, source, h)
    assert minconv > 1.9
コード例 #10
0
def test_interpolate_scalar_valued():
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    mesh = IntervalMesh(10, 0, 1)
    V1 = FunctionSpace(mesh, "CG", 1)
    V2 = FunctionSpace(mesh, "CG", 2)
    V3 = FunctionSpace(mesh, "CG", 3)

    x, = SpatialCoordinate(mesh)
    f = interpolate(x, V1)
    g = interpolate(sin(x), V2)
    u = Function(V3)
    u.interpolate(3 * f**2 + Constant(4.0) * g)

    J = assemble(u**2 * dx)
    rf = ReducedFunctional(J, Control(f))

    h = Function(V1)
    h.vector()[:] = rand(V1.dim())
    assert taylor_test(rf, f, h) > 1.9

    rf = ReducedFunctional(J, Control(g))
    h = Function(V2)
    h.vector()[:] = rand(V2.dim())
    assert taylor_test(rf, g, h) > 1.9
コード例 #11
0
def test_interpolate_bump_function():
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    mesh = UnitSquareMesh(10, 10)
    V = FunctionSpace(mesh, "CG", 2)

    x, y = SpatialCoordinate(mesh)
    cx = Constant(0.5)
    cy = Constant(0.5)
    f = interpolate(exp(-1 / (1 - (x - cx)**2) - 1 / (1 - (y - cy)**2)), V)

    J = assemble(f * y**3 * dx)
    rf = ReducedFunctional(J, [Control(cx), Control(cy)])

    h = [Constant(0.1), Constant(0.1)]
    assert taylor_test(rf, [cx, cy], h) > 1.9
コード例 #12
0
def test_interpolate_to_function_space():
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    mesh = UnitSquareMesh(1, 1)
    V = FunctionSpace(mesh, "CG", 1)
    W = FunctionSpace(mesh, "DG", 1)
    u = Function(V)

    x = SpatialCoordinate(mesh)
    u.interpolate(x[0])
    c = Constant(1.)
    w = interpolate((u + c) * u, W)

    J = assemble(w**2 * dx)
    rf = ReducedFunctional(J, Control(c))
    h = Constant(0.1)
    assert taylor_test(rf, Constant(1.), h) > 1.9
コード例 #13
0
def test_interpolate_with_arguments():
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    mesh = UnitSquareMesh(10, 10)
    V1 = FunctionSpace(mesh, "CG", 1)
    V2 = FunctionSpace(mesh, "CG", 2)

    x, y = SpatialCoordinate(mesh)
    expr = x + y
    f = interpolate(expr, V1)
    interpolator = Interpolator(TestFunction(V1), V2)
    u = interpolator.interpolate(f)

    J = assemble(u**2 * dx)
    rf = ReducedFunctional(J, Control(f))

    h = Function(V1)
    h.vector()[:] = rand(V1.dim())
    assert taylor_test(rf, f, h) > 1.9
コード例 #14
0
def test_supermesh_project_tlm(vector):
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    source, target_space = supermesh_setup()
    control = Control(source)
    target = project(source, target_space)
    J = assemble(inner(target, target) * dx)
    rf = ReducedFunctional(J, control)

    # Test replay with different input
    h = Function(source)
    h.assign(1.0)
    source.block_variable.tlm_value = h

    tape = get_working_tape()
    tape.evaluate_tlm()

    assert J.block_variable.tlm_value is not None
    assert taylor_test(rf, source, h, dJdm=J.block_variable.tlm_value) > 1.9
コード例 #15
0
def test_consecutive_nonlinear_solves():
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    mesh = UnitSquareMesh(1, 1)
    V = FunctionSpace(mesh, "CG", 1)
    uic = Constant(2.0)
    u1 = Function(V).assign(uic)
    u0 = Function(u1)
    v = TestFunction(V)
    F = v * u1**2 * dx - v * u0 * dx
    problem = NonlinearVariationalProblem(F, u1)
    solver = NonlinearVariationalSolver(problem)
    for i in range(3):
        u0.assign(u1)
        solver.solve()
    J = assemble(u1**16 * dx)
    rf = ReducedFunctional(J, Control(uic))
    h = Constant(0.01)
    assert taylor_test(rf, uic, h) > 1.9
コード例 #16
0
def test_interpolate_vector_valued():
    from firedrake_adjoint import ReducedFunctional, Control, taylor_test
    mesh = UnitSquareMesh(10, 10)
    V1 = VectorFunctionSpace(mesh, "CG", 1)
    V2 = VectorFunctionSpace(mesh, "DG", 0)
    V3 = VectorFunctionSpace(mesh, "CG", 2)

    x = SpatialCoordinate(mesh)
    f = interpolate(as_vector((x[0] * x[1], x[0] + x[1])), V1)
    g = interpolate(as_vector((sin(x[1]) + x[0], cos(x[0]) * x[1])), V2)
    u = Function(V3)
    u.interpolate(f * dot(f, g) - 0.5 * g)

    J = assemble(inner(f, g) * u**2 * dx)
    rf = ReducedFunctional(J, Control(f))

    h = Function(V1)
    h.vector()[:] = 1
    assert taylor_test(rf, f, h) > 1.9
コード例 #17
0
def test_supermesh_project_to_function_space():
    from firedrake_adjoint import ReducedFunctional, Control
    source, target_space = supermesh_setup()
    control = Control(source)
    target = project(source, target_space)
    J = assemble(target * dx)
    rf = ReducedFunctional(J, control)

    # Check forward conservation
    mass = assemble(source * dx)
    assert np.isclose(mass, J)

    # Test replay with the same input
    assert np.isclose(rf(source), J)

    # Test replay with different input
    h = Function(source)
    h.assign(10.0)
    assert np.isclose(rf(h), 10.0)
コード例 #18
0
def test_poisson_inverse_conductivity():
    # Have to import inside test to make sure cleanup fixtures work as intended
    from firedrake_adjoint import Control, ReducedFunctional, minimize

    # Manually set up annotation since test suite may have stopped it
    tape = get_working_tape()
    tape.clear_tape()
    set_working_tape(tape)
    continue_annotation()

    # Use pyadjoint to estimate an unknown conductivity in a
    # poisson-like forward model from point measurements
    m = UnitSquareMesh(2, 2)
    V = FunctionSpace(m, family='CG', degree=2)
    Q = FunctionSpace(m, family='CG', degree=2)

    # generate random "true" conductivity with beta distribution
    pcg = PCG64(seed=0)
    rg = RandomGenerator(pcg)
    # beta distribution
    q_true = rg.beta(Q, 1.0, 2.0)

    # Compute the true solution of the PDE.
    u_true = Function(V)
    v = TestFunction(V)
    f = Constant(1.0)
    k0 = Constant(0.5)
    bc = DirichletBC(V, 0, 'on_boundary')
    F = (k0 * exp(q_true) * inner(grad(u_true), grad(v)) - f * v) * dx
    solve(F == 0, u_true, bc)

    # Generate random point cloud
    num_points = 2
    np.random.seed(0)
    xs = np.random.random_sample((num_points, 2))
    point_cloud = VertexOnlyMesh(m, xs)

    # Prove the the point cloud coordinates are correct
    assert((point_cloud.coordinates.dat.data_ro == xs).all())

    # Generate "observed" data
    generator = np.random.default_rng(0)
    signal_to_noise = 20
    U = u_true.dat.data_ro[:]
    u_range = U.max() - U.min()
    σ = Constant(u_range / signal_to_noise)
    ζ = generator.standard_normal(len(xs))
    u_obs_vals = np.array(u_true.at(xs)) + float(σ) * ζ

    # Store data on the point_cloud
    P0DG = FunctionSpace(point_cloud, 'DG', 0)
    u_obs = Function(P0DG)
    u_obs.dat.data[:] = u_obs_vals

    # Run the forward model
    u = Function(V)
    q = Function(Q)
    bc = DirichletBC(V, 0, 'on_boundary')
    F = (k0 * exp(q) * inner(grad(u), grad(v)) - f * v) * dx
    solve(F == 0, u, bc)

    # Two terms in the functional
    misfit_expr = 0.5 * ((u_obs - interpolate(u, P0DG)) / σ)**2
    α = Constant(0.5)
    regularisation_expr = 0.5 * α**2 * inner(grad(q), grad(q))

    # Form functional and reduced functional
    J = assemble(misfit_expr * dx) + assemble(regularisation_expr * dx)
    q̂ = Control(q)
    Ĵ = ReducedFunctional(J, q̂)

    # Estimate q using Newton-CG which evaluates the hessian action
    minimize(Ĵ, method='Newton-CG', options={'disp': True})

    # Make sure annotation is stopped
    tape.clear_tape()
    pause_annotation()
コード例 #19
0
def test_replay(op, order, power):
    """
    Given source and target functions of some `order`,
    verify that replaying the tape associated with the
    augmented operators +=, -=, *= and /= gives the same
    result as a hand derivation.
    """
    from firedrake_adjoint import ReducedFunctional, Control
    mesh = UnitSquareMesh(4, 4)
    x, y = SpatialCoordinate(mesh)
    V = FunctionSpace(mesh, "CG", order)

    # Source and target functions
    s = interpolate(x + 1, V)
    t = interpolate(y + 1, V)
    s_orig = s.copy(deepcopy=True)
    t_orig = t.copy(deepcopy=True)
    control_s = Control(s)
    control_t = Control(t)

    # Apply the operator
    if op == 'iadd':
        t += s
    elif op == 'isub':
        t -= s
    elif op == 'imul':
        t *= s
    elif op == 'idiv':
        t /= s
    else:
        raise ValueError("Operator '{:s}' not recognised".format(op))

    # Construct some nontrivial reduced functional
    f = lambda X: X**power
    J = assemble(f(t) * dx)
    rf_s = ReducedFunctional(J, control_s)
    rf_t = ReducedFunctional(J, control_t)

    with stop_annotating():

        # Check for consistency with the same input
        assert np.isclose(rf_s(s_orig), rf_s(s_orig))
        assert np.isclose(rf_t(t_orig), rf_t(t_orig))

        # Check for consistency with different input
        ss = s_orig.copy(deepcopy=True)
        tt = t_orig.copy(deepcopy=True)
        if op == 'iadd':
            ss += ss
            tt += tt
        elif op == 'isub':
            ss -= ss
            tt -= tt
        elif op == 'imul':
            ss *= ss
            tt *= tt
        elif op == 'idiv':
            ss /= ss
            tt /= tt
        assert np.isclose(rf_s(t_orig), assemble(f(tt) * dx))
        assert np.isclose(rf_t(s_orig), assemble(f(ss) * dx))