Beispiel #1
0
def pytest_runtest_teardown(item, nextitem):
    """Clear Thetis caches after running a test"""
    from firedrake.tsfc_interface import TSFCKernel
    from pyop2.op2 import Kernel
    from pyop2.base import JITModule
    from firedrake_adjoint import get_working_tape

    # disgusting hack, clear the Class-Cached objects in PyOP2 and
    # Firedrake, otherwise these will never be collected.  The Kernels
    # get very big with bendy on.
    Kernel._cache.clear()
    TSFCKernel._cache.clear()
    JITModule._cache.clear()
    # clear the adjoint tape, so subsequent tests don't interfere
    get_working_tape().clear_tape()
Beispiel #2
0
 def update(self, x, flag, iteration):
     """Update domain and solution to state and adjoint equation."""
     if self.Q.update_domain(x):
         try:
             # We use pyadjoint to calculate adjoint and shape derivatives,
             # in order to do this we need to "record a tape of the forward
             # solve", pyadjoint will then figure out all necessary
             # adjoints.
             import firedrake_adjoint as fda
             tape = fda.get_working_tape()
             tape.clear_tape()
             # ensure we are annotating
             from pyadjoint.tape import annotate_tape
             safety_counter = 0
             while not annotate_tape():
                 safety_counter += 1
                 fda.continue_annotation()
                 if safety_counter > 1e2:
                     import sys
                     sys.exit('Cannot annotate even after 100 attempts.')
             mesh_m = self.J.Q.mesh_m
             s = fd.Function(self.J.V_m)
             mesh_m.coordinates.assign(mesh_m.coordinates + s)
             self.s = s
             self.c = fda.Control(s)
             self.e.solve()
             Jpyadj = fd.assemble(self.J.value_form())
             self.Jred = fda.ReducedFunctional(Jpyadj, self.c)
             fda.pause_annotation()
         except fd.ConvergenceError:
             if self.cb is not None:
                 self.cb()
             raise
     if iteration >= 0 and self.cb is not None:
         self.cb()
Beispiel #3
0
 def update(self, x, flag, iteration):
     """Update domain and solution to state and adjoint equation."""
     if self.Q.update_domain(x):
         try:
             # We use pyadjoint to calculate adjoint and shape derivatives,
             # in order to do this we need to "record a tape of the forward
             # solve", pyadjoint will then figure out all necessary
             # adjoints.
             tape = fda.get_working_tape()
             tape.clear_tape()
             fda.continue_annotation()
             mesh_m = self.J.Q.mesh_m
             s = fda.Function(self.J.V_m)
             mesh_m.coordinates.assign(mesh_m.coordinates + s)
             self.s = s
             self.c = fda.Control(s)
             self.e.solve()
             Jpyadj = fda.assemble(self.J.value_form())
             self.Jred = fda.ReducedFunctional(Jpyadj, self.c)
             fda.pause_annotation()
         except fd.ConvergenceError:
             if self.cb is not None:
                 self.cb()
             raise
     if iteration >= 0 and self.cb is not None:
         self.cb()
Beispiel #4
0
def gradient_test_acoustic(model,
                           mesh,
                           V,
                           comm,
                           vp_exact,
                           vp_guess,
                           mask=None):  #{{{
    import firedrake_adjoint as fire_adj
    with fire_adj.stop_annotating():
        if comm.comm.rank == 0:
            print('######## Starting gradient test ########', flush=True)

        sources = spyro.Sources(model, mesh, V, comm)
        receivers = spyro.Receivers(model, mesh, V, comm)

        wavelet = spyro.full_ricker_wavelet(
            model["timeaxis"]["dt"],
            model["timeaxis"]["tf"],
            model["acquisition"]["frequency"],
        )
        point_cloud = receivers.set_point_cloud(comm)
        # simulate the exact model
        if comm.comm.rank == 0:
            print('######## Running the exact model ########', flush=True)
        p_exact_recv = forward(model, mesh, comm, vp_exact, sources, wavelet,
                               point_cloud)

    # simulate the guess model
    if comm.comm.rank == 0:
        print('######## Running the guess model ########', flush=True)
    p_guess_recv, Jm = forward(model,
                               mesh,
                               comm,
                               vp_guess,
                               sources,
                               wavelet,
                               point_cloud,
                               fwi=True,
                               true_rec=p_exact_recv)
    if comm.comm.rank == 0:
        print("\n Cost functional at fixed point : " + str(Jm) + " \n ",
              flush=True)

    # compute the gradient of the control (to be verified)
    if comm.comm.rank == 0:
        print(
            '######## Computing the gradient by automatic differentiation ########',
            flush=True)
    control = fire_adj.Control(vp_guess)
    dJ = fire_adj.compute_gradient(Jm, control)
    if mask:
        dJ *= mask

    # File("gradient.pvd").write(dJ)

    #steps = [1e-3, 1e-4, 1e-5, 1e-6, 1e-7]  # step length
    #steps = [1e-4, 1e-5, 1e-6, 1e-7]  # step length
    steps = [1e-5, 1e-6, 1e-7, 1e-8]  # step length
    with fire_adj.stop_annotating():
        delta_m = Function(V)  # model direction (random)
        delta_m.assign(dJ)
        Jhat = fire_adj.ReducedFunctional(Jm, control)
        derivative = enlisting.Enlist(Jhat.derivative())
        hs = enlisting.Enlist(delta_m)

        projnorm = sum(hi._ad_dot(di) for hi, di in zip(hs, derivative))

        # this deepcopy is important otherwise pertubations accumulate
        vp_original = vp_guess.copy(deepcopy=True)

        if comm.comm.rank == 0:
            print(
                '######## Computing the gradient by finite diferences ########',
                flush=True)
        errors = []
        for step in steps:  # range(3):
            # steps.append(step)
            # perturb the model and calculate the functional (again)
            # J(m + delta_m*h)
            vp_guess = vp_original + step * delta_m
            p_guess_recv, Jp = forward(model,
                                       mesh,
                                       comm,
                                       vp_guess,
                                       sources,
                                       wavelet,
                                       point_cloud,
                                       fwi=True,
                                       true_rec=p_exact_recv)

            fd_grad = (Jp - Jm) / step
            if comm.comm.rank == 0:
                print("\n Cost functional for step " + str(step) + " : " +
                      str(Jp) + ", fd approx.: " + str(fd_grad) +
                      ", grad'*dir : " + str(projnorm) + " \n ",
                      flush=True)

            errors.append(100 * ((fd_grad - projnorm) / projnorm))

    fire_adj.get_working_tape().clear_tape()

    # all errors less than 1 %
    errors = np.array(errors)
    assert (np.abs(errors) < 5.0).all()
Beispiel #5
0
# In[3]:


from firedrake import exp, inner, grad, dx
u_true = firedrake.Function(V)
v = firedrake.TestFunction(V)
f = Constant(1.0)
k0 = Constant(0.5)
bc = firedrake.DirichletBC(V, 0, 'on_boundary')
F = (k0 * exp(q_true) * inner(grad(u_true), grad(v)) - f * v) * dx
firedrake.solve(F == 0, u_true, bc)

print('Made fake u_true')

# Clear tape since don't need to have taped above
tape = firedrake_adjoint.get_working_tape()
tape.clear_tape()

# ## Generating Observational Data $u_{obs}$
# We run up in powers of 2 until we have plenty of observations per cell (on average)

# In[4]:

signal_to_noise = 20
U = u_true.dat.data_ro[:]
u_range = U.max() - U.min()
σ = firedrake.Constant(u_range / signal_to_noise)

methods = ['point-cloud', 'nearest', 'linear', 'clough-tocher', 'gaussian']

min_power_of_2 = 2
Beispiel #6
0
def heat_exchanger_3D():
    parser = argparse.ArgumentParser(description="Level set method parameters")
    parser.add_argument(
        "--nu",
        action="store",
        dest="nu",
        type=float,
        help="Kinematic Viscosity",
        default=1.0,
    )
    parser.add_argument(
        "--brinkmann_penalty",
        action="store",
        dest="brinkmann_penalty",
        type=float,
        help="Brinkmann term",
        default=1e5,
    )
    parser.add_argument(
        "--refinement",
        action="store",
        dest="refinement",
        type=int,
        help="Level of refinement",
        default=0,
    )
    parser.add_argument(
        "--pressure_drop_constraint",
        action="store",
        dest="pressure_drop_constraint",
        type=float,
        help="Pressure drop constraint",
        default=10.0,
    )
    parser.add_argument(
        "--n_iters",
        dest="n_iters",
        type=int,
        action="store",
        default=1000,
        help="Number of optimization iterations",
    )
    parser.add_argument(
        "--output_dir",
        dest="output_dir",
        type=str,
        action="store",
        default="./",
        help="Output folder",
    )
    parser.add_argument(
        "--type",
        dest="type_he",
        type=str,
        action="store",
        default="parallel",
        help="Type of heat exchanger: parallel or counter",
    )
    opts = parser.parse_args()
    print(f"Parameters used: {opts}")

    beta_param = 0.4
    mesh = fd.Mesh("./box_heat_exch.msh")

    from parameters_box import (
        INLET2,
        INLET1,
        OUTLET1,
        OUTLET2,
        INMOUTH1,
        INMOUTH2,
        OUTMOUTH1,
        OUTMOUTH2,
    )

    if opts.type_he == "counter":
        INLET1, OUTLET1 = OUTLET1, INLET1
    elif opts.type_he == "u_flow":
        INLET2, OUTLET1 = OUTLET1, INLET2
        OUTMOUTH1, INMOUTH2 = INMOUTH2, OUTMOUTH1

    markers = {
        "WALLS": WALLS,
        "INLET1": INLET1,
        "INLET2": INLET2,
        "OUTLET1": OUTLET1,
        "OUTLET2": OUTLET2,
    }

    no_flow_domain_1 = [INMOUTH2, OUTMOUTH2]
    no_flow_domain_2 = [INMOUTH1, OUTMOUTH1]
    no_flow = no_flow_domain_1.copy()
    no_flow.extend(no_flow_domain_2)
    mesh = mark_no_flow_regions(mesh, no_flow, no_flow)

    mh = fd.MeshHierarchy(mesh, opts.refinement)
    mesh = mh[-1]

    pressure_drop_constraint = opts.pressure_drop_constraint
    pressure_drop_1 = pressure_drop_constraint
    pressure_drop_2 = pressure_drop_constraint

    S = fd.VectorFunctionSpace(mesh, "CG", 1)

    PHI = fd.FunctionSpace(mesh, "CG", 1)
    phi = fd.Function(PHI, name="LevelSet")
    x, y, z = fd.SpatialCoordinate(mesh)

    ω = 0.25
    phi_expr = sin(y * pi / ω) * cos(x * pi / ω) * sin(
        z * pi / ω) - fd.Constant(0.2)

    checkpoints = is_checkpoint(opts.output_dir)
    if checkpoints:
        current_iter = read_checkpoint(checkpoints, phi)
        with open(f"{opts.output_dir}/brinkmann_penalty.txt",
                  "r") as txt_brinkmann:
            brinkmann_penalty_initial = fd.Constant(txt_brinkmann.read())
        print(
            f"Current brinkmann term: {brinkmann_penalty_initial.values()[0]}")
    else:
        with stop_annotating():
            phi.interpolate(phi_expr)
        current_iter = 0
        brinkmann_penalty_initial = fd.Constant(opts.brinkmann_penalty)

    P2 = fd.VectorElement("CG", mesh.ufl_cell(), 1)
    P1 = fd.FiniteElement("CG", mesh.ufl_cell(), 1)
    TH = P2 * P1
    W = fd.FunctionSpace(mesh, TH)
    print(f"DOFS: {W.dim()}")

    T = fd.FunctionSpace(mesh, "CG", 1)

    global_counter = count(current_iter)

    def receive_signal(signum, stack):
        iter_current = next(copy(global_counter))
        print(f"Received: {signum}, iter: {iter_current}")
        with fd.HDF5File(
                f"{opts.output_dir}/checkpoint_iter_{iter_current}.h5",
                "w") as checkpoint:
            checkpoint.write(phi, "/checkpoint")
        with open(f"{opts.output_dir}/brinkmann_penalty.txt",
                  "w") as txt_brinkmann:
            txt_brinkmann.write(str(brinkmann_penalty.values()[0]))

    signal.signal(signal.SIGHUP, receive_signal)

    phi_pvd = fd.File(
        f"{opts.output_dir}/phi_evolution.pvd",
        target_degree=1,
        target_continuity=fd.H1,
        mode="a",
    )
    ns1 = fd.File(f"{opts.output_dir}/navier_stokes_1.pvd", mode="a")
    ns2 = fd.File(f"{opts.output_dir}/navier_stokes_2.pvd", mode="a")
    temperature = fd.File(f"{opts.output_dir}/temperature.pvd", mode="a")
    temperature_pvd = fd.Function(T)

    def termination_event_1():
        p1_constraint = P1control.tape_value() - 1
        p2_constraint = P2control.tape_value() - 1
        event_value = max(p1_constraint, p2_constraint)
        print(f"Value event: {event_value}")
        return event_value

    def termination_event_2():
        iter_current = next(copy(global_counter))
        print(f"Value event iter count: {iter_current}")
        return float(iter_current % 500)

    brinkmann_penalty_initial_value = brinkmann_penalty_initial.values()[0]
    if brinkmann_penalty_initial_value > opts.brinkmann_penalty:
        termination_events = [termination_event_2, termination_event_2]
        brinkmann_pen_terms = [
            brinkmann_penalty_initial,
            fd.Constant(brinkmann_penalty_initial_value * 10),
        ]
    else:
        termination_events = [termination_event_1, None]
        brinkmann_pen_terms = [
            brinkmann_penalty_initial,
            fd.Constant(brinkmann_penalty_initial_value * 5),
        ]

    for termination_event, brinkmann_penalty in zip(termination_events,
                                                    brinkmann_pen_terms):

        s = fd.Function(S, name="deform")
        mesh.coordinates.assign(mesh.coordinates + s)
        # w_sol1, w_sol2, t = forward(brinkmann_penalty)

        w_sol1, w_sol2, t = forward(
            W,
            T,
            phi,
            opts,
            brinkmann_penalty,
            no_flow_domain_1=no_flow_domain_1,
            no_flow_domain_2=no_flow_domain_2,
            markers=markers,
        )

        w_sol1_control = fda.Control(w_sol1)
        w_sol2_control = fda.Control(w_sol2)
        t_control = fda.Control(t)

        J = heat_flux(w_sol2, t, OUTLET2)
        J_hot = heat_flux(w_sol1, t, OUTLET1)
        Pdrop1 = pressure_drop(w_sol1, INLET1, OUTLET1, pressure_drop_1)
        Pdrop2 = pressure_drop(w_sol2, INLET2, OUTLET2, pressure_drop_2)
        print(f"Cold flux: {J}, hot flux: {J_hot}")

        c = fda.Control(s)
        J_hot_control = fda.Control(J_hot)

        def deriv_cb(phi):
            with stop_annotating():
                iter = next(global_counter)
                print(f"Hot flux: {J_hot_control.tape_value()}")
                if iter % 15 == 0:
                    u_sol1, p_sol1 = w_sol1_control.tape_value().split()
                    u_sol2, p_sol2 = w_sol2_control.tape_value().split()

                    u_sol1.rename("Velocity1")
                    p_sol1.rename("Pressure1")

                    u_sol2.rename("Velocity2")
                    p_sol2.rename("Pressure2")

                    ns1.write(u_sol1, p_sol1, time=iter)
                    ns2.write(u_sol2, p_sol2, time=iter)
                    phi_pvd.write(phi[0], time=iter)

                    temperature_pvd.assign(t_control.tape_value())
                    temperature_pvd.rename("temperature")
                    temperature.write(temperature_pvd, time=iter)

        # Reduced Functionals
        Jhat = LevelSetFunctional(J, c, phi, derivative_cb_pre=deriv_cb)
        P1hat = LevelSetFunctional(Pdrop1, c, phi)
        P1control = fda.Control(Pdrop1)

        P2hat = LevelSetFunctional(Pdrop2, c, phi)
        P2control = fda.Control(Pdrop2)
        print("Pressure drop 1 {:.5f}".format(Pdrop1))
        print("Pressure drop 2 {:.5f}".format(Pdrop2))

        reg_solver = RegularizationSolver(
            S,
            mesh,
            beta=beta_param,
            gamma=1e6,
            dx=dx,
            design_domain=DESIGN_DOMAIN,
            solver_parameters=regularization_solver_parameters,
        )

        tol = 1e-7
        dt = 0.02
        params = {
            "alphaC": 0.1,
            "debug": 5,
            "alphaJ": 0.1,
            "dt": dt,
            "K": 1e-3,
            "maxit": opts.n_iters,
            "maxtrials": 10,
            "itnormalisation": 10,
            "tol_merit":
            1e-2,  # new merit can be within 1% of the previous merit
            # "normalize_tol" : -1,
            "tol": tol,
        }

        hj_solver_parameters["ts_dt"] = dt / 50.0
        solver_parameters = {
            "hj_solver": hj_solver_parameters,
            "reinit_solver": reinit_solver_parameters,
        }

        problem = InfDimProblem(
            Jhat,
            reg_solver,
            ineqconstraints=[
                Constraint(P1hat, 1.0, P1control),
                Constraint(P2hat, 1.0, P2control),
            ],
            reinit_distance=0.08,
            solver_parameters=solver_parameters,
        )
        problem.set_termination_event(termination_event,
                                      termination_tolerance=1e-1)

        _ = nlspace_solve(problem, params)
        fda.get_working_tape().clear_tape()