def test_parallel_source(): comm = spyro.utils.mpi_init(options) mesh, V = spyro.io.read_mesh(options, comm) vp = Function(V).assign(1.0) sources = spyro.Sources(options, mesh, V, comm) receivers = spyro.Receivers(options, mesh, V, comm) wavelet = spyro.full_ricker_wavelet( options["timeaxis"]["dt"], options["timeaxis"]["tf"], options["acquisition"]["frequency"], ) f, r = forward( options, mesh, comm, vp, sources, wavelet, receivers, ) #print(np.amax(np.abs(r))) #spyro.io.save_shots('serial_shot.dat', r) r_s = spyro.io.load_shots(os.getcwd() + '/test/serial_shot.dat') assert np.amax(np.abs(r - r_s)) < 1e-16
def run_solve(timestep_method, method, model, mesh, expr): testmodel = deepcopy(model) if method == "KMV": variant = "KMV" testmodel["opts"]["quadrature"] = "KMV" else: variant = "equispaced" comm = spyro.utils.mpi_init(testmodel) element = FiniteElement(method, mesh.ufl_cell(), degree=1, variant=variant) V = FunctionSpace(mesh, element) excitation = spyro.Sources(testmodel, mesh, V, comm) wavelet = spyro.full_ricker_wavelet(dt=0.001, tf=1.0, freq=2.0) receivers = spyro.Receivers(testmodel, mesh, V, comm) if timestep_method == "central": p, _ = spyro.solvers.forward(testmodel, mesh, comm, Constant(1.0), excitation, wavelet, receivers) elif timestep_method == "ssprk": p, _ = spyro.solvers.SSPRK3(testmodel, mesh, comm, Constant(1.0), excitation, receivers) expr = expr(*SpatialCoordinate(mesh)) return errornorm(interpolate(expr, V), p[-1])
def wave_solver(model, mesh, comm, output=False): method = model["opts"]["method"] degree = model['opts']['degree'] element = fire.FiniteElement(method, mesh.ufl_cell(), degree=degree, variant="KMV") V = fire.FunctionSpace(mesh, element) vp = fire.Constant(1.429) if comm.ensemble_comm.rank == 0 and comm.comm.rank == 0: print("Finding sources and receivers", flush=True) sources = spyro.Sources(model, mesh, V, comm) receivers = spyro.Receivers(model, mesh, V, comm) if comm.ensemble_comm.rank == 0 and comm.comm.rank == 0: print("Starting simulation", flush=True) wavelet = spyro.full_ricker_wavelet( dt=model["timeaxis"]["dt"], tf=model["timeaxis"]["tf"], freq=model["acquisition"]["frequency"], ) p, p_r = spyro.solvers.forward(model, mesh, comm, vp, sources, wavelet, receivers, output=output) return p_r
def wave_solver(model, G, comm=False): minimum_mesh_velocity = model['testing_parameters'][ 'minimum_mesh_velocity'] model["mesh"]["meshfile"] = "meshes/2Dhomogeneous" + str(G) + ".msh" try: mesh, V = spyro.io.read_mesh(model, comm) except: model = generate_mesh(model, G, comm) mesh, V = spyro.io.read_mesh(model, comm) if model['testing_parameters']['experiment_type'] == 'homogeneous': vp_exact = fire.Constant(minimum_mesh_velocity) elif model['testing_parameters']['experiment_type'] == 'heterogeneous': vp_exact = spyro.io.interpolate(model, mesh, V, guess=False) if model["opts"]["method"] == 'KMV': estimate_max_eigenvalue = True else: estimate_max_eigenvalue = False new_dt = 0.2 * spyro.estimate_timestep( mesh, V, vp_exact, estimate_max_eigenvalue=estimate_max_eigenvalue) model['timeaxis']['dt'] = comm.comm.allreduce(new_dt, op=MPI.MIN) if comm.comm.rank == 0: print( f"Maximum stable timestep is: {model['timeaxis']['dt']} seconds", flush=True, ) if model['timeaxis']['dt'] > 0.001: model['timeaxis']['dt'] = 0.001 if comm.comm.rank == 0: print( f"Timestep used is: {model['timeaxis']['dt']} seconds", flush=True, ) sources = spyro.Sources(model, mesh, V, comm) receivers = spyro.Receivers(model, mesh, V, comm) wavelet = spyro.full_ricker_wavelet( dt=model["timeaxis"]["dt"], tf=model["timeaxis"]["tf"], freq=model["acquisition"]["frequency"], ) for sn in range(model["acquisition"]["num_sources"]): if spyro.io.is_owner(comm, sn): t1 = time.time() p_field, p_recv = spyro.solvers.forward(model, mesh, comm, vp_exact, sources, wavelet, receivers, source_num=sn, output=False) print(time.time() - t1) return p_recv
"nspool": 1000, # how frequently to output solution to pvds "fspool": 10, # how frequently to save solution to RAM "skip": 4, } comm = spyro.utils.mpi_init(model) mesh, V = spyro.io.read_mesh(model, comm) if COMM_WORLD.rank == 0: print(f"The mesh has {V.dim()} degrees of freedom") vp = spyro.io.interpolate(model, mesh, V, guess=True) if comm.ensemble_comm.rank == 0: File("guess_velocity.pvd", comm=comm.comm).write(vp) sources = spyro.Sources(model, mesh, V, comm) receivers = spyro.Receivers(model, mesh, V, comm) wavelet = spyro.full_ricker_wavelet( dt=model["timeaxis"]["dt"], tf=model["timeaxis"]["tf"], freq=model["acquisition"]["frequency"], ) if comm.ensemble_comm.rank == 0: control_file = File(outdir + "control.pvd", comm=comm.comm) grad_file = File(outdir + "grad.pvd", comm=comm.comm) quad_rule = finat.quadrature.make_quadrature( V.finat_element.cell, V.ufl_element().degree(), "KMV" ) dxlump = dx(rule=quad_rule) water = np.where(vp.dat.data[:] < 1.51) class L2Inner(object): def __init__(self):
def _test_gradient(options, pml=False): comm = spyro.utils.mpi_init(options) mesh, V = spyro.io.read_mesh(options, comm) if pml: vp_exact = _make_vp_exact_pml(V, mesh) z, x = SpatialCoordinate(mesh) Lx = model_pml["mesh"]["Lx"] Lz = model_pml["mesh"]["Lz"] x1 = 0.0 x2 = Lx z1 = 0.0 z2 = -Lz boxx1 = Function(V).interpolate(conditional(x > x1, 1.0, 0.0)) boxx2 = Function(V).interpolate(conditional(x < Lx, 1.0, 0.0)) boxz1 = Function(V).interpolate(conditional(z > z2, 1.0, 0.0)) mask = Function(V).interpolate(boxx1 * boxx2 * boxz1) File("mask.pvd").write(mask) else: vp_exact = _make_vp_exact(V, mesh) mask = Function(V).assign(1.0) vp_guess = _make_vp_guess(V, mesh) sources = spyro.Sources(options, mesh, V, comm) receivers = spyro.Receivers(options, mesh, V, comm) wavelet = spyro.full_ricker_wavelet( options["timeaxis"]["dt"], options["timeaxis"]["tf"], options["acquisition"]["frequency"], ) # simulate the exact model p_exact, p_exact_recv = forward( options, mesh, comm, vp_exact, sources, wavelet, receivers, ) # simulate the guess model p_guess, p_guess_recv = forward( options, mesh, comm, vp_guess, sources, wavelet, receivers, ) misfit = p_exact_recv - p_guess_recv qr_x, _, _ = quadrature.quadrature_rules(V) Jm = functional(options, misfit) print("\n Cost functional at fixed point : " + str(Jm) + " \n ") # compute the gradient of the control (to be verified) dJ = gradient(options, mesh, comm, vp_guess, receivers, p_guess, misfit) dJ *= mask File("gradient.pvd").write(dJ) steps = [1e-3, 1e-4, 1e-5] # , 1e-6] # step length delta_m = Function(V) # model direction (random) delta_m.assign(dJ) # this deepcopy is important otherwise pertubations accumulate vp_original = vp_guess.copy(deepcopy=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 = forward( options, mesh, comm, vp_guess, sources, wavelet, receivers, ) Jp = functional(options, p_exact_recv - p_guess_recv) projnorm = assemble(mask * dJ * delta_m * dx(rule=qr_x)) fd_grad = (Jp - Jm) / step print( "\n Cost functional for step " + str(step) + " : " + str(Jp) + ", fd approx.: " + str(fd_grad) + ", grad'*dir : " + str(projnorm) + " \n ", ) errors.append(100 * ((fd_grad - projnorm) / projnorm)) # step /= 2 # all errors less than 1 % errors = np.array(errors) assert (np.abs(errors) < 5.0).all()
def test_forward_5shots(): model = {} model["opts"] = { "method": "KMV", # either CG or KMV "quadrature": "KMV", # Equi or KMV "degree": 4, # p order "dimension": 2, # dimension } model["parallelism"] = { "type": "automatic", } model["mesh"] = { "Lz": 3.5, # depth in km - always positive "Lx": 17.0, # width in km - always positive "Ly": 0.0, # thickness in km - always positive "meshfile": "meshes/marmousi_5Hz.msh", "initmodel": None, "truemodel": "velocity_models/vp_marmousi-ii.hdf5", } model["BCs"] = { "status": True, # True or false "outer_bc": "non-reflective", # None or non-reflective (outer boundary condition) "damping_type": "polynomial", # polynomial, hyperbolic, shifted_hyperbolic "exponent": 2, # damping layer has a exponent variation "cmax": 4.5, # maximum acoustic wave velocity in PML - km/s "R": 1e-6, # theoretical reflection coefficient "lz": 0.9, # thickness of the PML in the z-direction (km) - always positive "lx": 0.9, # thickness of the PML in the x-direction (km) - always positive "ly": 0.0, # thickness of the PML in the y-direction (km) - always positive } model["acquisition"] = { "source_type": "Ricker", "source_pos": spyro.create_transect((-0.1, 1.0), (-0.1, 15.0), 5), "frequency": 5.0, "delay": 1.0, "receiver_locations": spyro.create_transect((-0.1, 1.0), (-0.1, 15.0),13), } model["timeaxis"] = { "t0": 0.0, # Initial time for event "tf": 3.00, # Final time for event "dt": 0.001, "amplitude": 1, # the Ricker has an amplitude of 1. "nspool": 100, # how frequently to output solution to pvds "fspool": 99999, # how frequently to save solution to RAM } dt=model["timeaxis"]["dt"] final_time=model["timeaxis"]["tf"] comm = spyro.utils.mpi_init(model) mesh, V = spyro.io.read_mesh(model, comm) vp = spyro.io.interpolate(model, mesh, V, guess=False) if comm.ensemble_comm.rank == 0: File("true_velocity.pvd", comm=comm.comm).write(vp) sources = spyro.Sources(model, mesh, V, comm) receivers = spyro.Receivers(model, mesh, V, comm) wavelet = spyro.full_ricker_wavelet( dt=model["timeaxis"]["dt"], tf=model["timeaxis"]["tf"], freq=model["acquisition"]["frequency"], ) p, p_r = spyro.solvers.forward(model, mesh, comm, vp, sources, wavelet, receivers) pass_error_test = False for source_id in range(len(model["acquisition"]["source_pos"])): if comm.ensemble_comm.rank == (source_id % comm.ensemble_comm.size): receiver_in_source_index= get_receiver_in_source_location(source_id, model) if source_id != len(model["acquisition"]["source_pos"])-1 or source_id == 0: receiver_comparison_index = receiver_in_source_index + 1 else: receiver_comparison_index = receiver_in_source_index - 1 error_percent = compare_velocity(p_r, receiver_in_source_index, receiver_comparison_index, model,dt) if error_percent < 5: pass_error_test = True print(f"For source = {source_id}: test = {pass_error_test}", flush = True) spyro.plots.plot_shots(model, comm, p_r, vmin=-1e-3, vmax=1e-3) spyro.io.save_shots(model, comm, p_r) assert pass_error_test
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()
def test_forward_3d(tf=0.6): model = {} model["opts"] = { "method": "KMV", # either CG or KMV "quadrature": "KMV", # Equi or KMV "degree": 3, # p order "dimension": 3, # dimension } model["parallelism"] = {"type": "automatic"} # automatic", model["mesh"] = { "Lz": 5.175, # depth in km - always positive "Lx": 7.50, # width in km - always positive "Ly": 7.50, # thickness in km - always positive "meshfile": "meshes/overthrust_3D_true_model.msh", "initmodel": "velocity_models/overthrust_3D_guess_model.hdf5", "truemodel": "velocity_models/overthrust_3D_true_model.hdf5", } model["BCs"] = { "status": True, # True or false "outer_bc": "non-reflective", # None or non-reflective (outer boundary condition) "damping_type": "polynomial", # polynomial, hyperbolic, shifted_hyperbolic "exponent": 2, # damping layer has a exponent variation "cmax": 6.0, # maximum acoustic wave velocity in PML - km/s "R": 1e-6, # theoretical reflection coefficient "lz": 0.75, # thickness of the PML in the z-direction (km) - always positive "lx": 0.75, # thickness of the PML in the x-direction (km) - always positive "ly": 0.75, # thickness of the PML in the y-direction (km) - always positive } model["acquisition"] = { "source_type": "Ricker", "source_pos": [(-0.15, 0.25, 0.25)], "frequency": 5.0, "delay": 1.0, "receiver_locations": [(-0.15, 0.25, 0.25), (-0.15, 0.3, 0.25), (-0.15, 0.35, 0.25), (-0.15, 0.4, 0.25), (-0.15, 0.45, 0.25), (-0.15, 0.5, 0.25), (-0.15, 0.55, 0.25), (-0.15, 0.6, 0.25)], } model["aut_dif"] = {"status": False} model["timeaxis"] = { "t0": 0.0, # Initial time for event "tf": tf, # Final time for event "dt": 0.00075, "amplitude": 1, # the Ricker has an amplitude of 1. "nspool": 100, # how frequently to output solution to pvds "fspool": 99999, # how frequently to save solution to RAM } comm = spyro.utils.mpi_init(model) mesh, V = spyro.io.read_mesh(model, comm) vp = spyro.io.interpolate(model, mesh, V, guess=False) if comm.ensemble_comm.rank == 0: File("true_velocity.pvd", comm=comm.comm).write(vp) sources = spyro.Sources(model, mesh, V, comm) receivers = spyro.Receivers(model, mesh, V, comm) wavelet = spyro.full_ricker_wavelet( dt=model["timeaxis"]["dt"], tf=model["timeaxis"]["tf"], freq=model["acquisition"]["frequency"], ) p, p_r = spyro.solvers.forward(model, mesh, comm, vp, sources, wavelet, receivers, output=False) dt = model["timeaxis"]["dt"] final_time = model["timeaxis"]["tf"] pass_error_test = True if comm.comm.rank == 0: error_percent = compare_velocity(p_r, 0, 7, model, dt) if error_percent < 5: pass_error_test = True else: pass_error_test = False assert pass_error_test