Example #1
0
def handle_exit_annotation():
    yield
    # Since importing firedrake_adjoint modifies a global variable, we need to
    # pause annotations at the end of the module
    annotate = annotate_tape()
    if annotate:
        pause_annotation()
Example #2
0
    def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs)
        # stop any annotation that might be ongoing as we only need to record
        # what happens in self.solvePDE()
        from pyadjoint.tape import pause_annotation, annotate_tape
        if annotate_tape():
            pause_annotation()
Example #3
0
    def __init__(self, J: Objective, e: PdeConstraint):
        if not isinstance(J, ShapeObjective):
            msg = "PDE constraints are currently only supported" \
                  + " for shape objectives."
            raise NotImplementedError(msg)

        msg = "ReducedObjective is deprecated and may be removed" \
              + "in the future. Use PDEconstrainedObjective instead."
        print(msg)

        super().__init__(J.Q, J.cb)
        self.J = J
        self.e = e
        # stop any annotation that might be ongoing as we only need to record
        # what's happening in e.solve()
        from pyadjoint.tape import pause_annotation, annotate_tape
        annotate = annotate_tape()
        if annotate:
            pause_annotation()
Example #4
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()