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
"t0": 0.0, # Initial time for event "tf": 5.00, # Final time for event "dt": 0.001, "amplitude": 1, # the Ricker has an amplitude of 1. "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)
def test_gradient_talyor_remainder_v2(): from ROL.firedrake_vector import FiredrakeVector as FeVector import ROL comm = spyro.utils.mpi_init(model) mesh, V = spyro.io.read_mesh(model, comm) vp_guess = _make_vp_guess(V, mesh) sources = spyro.Sources(model, mesh, V, comm) receivers = spyro.Receivers(model, mesh, V, comm) vp_exact = _make_vp_exact(V, mesh) _, p_exact_recv = spyro.solvers.forward(model, mesh, comm, vp_exact, sources, wavelet, receivers) qr_x, _, _ = spyro.domains.quadrature.quadrature_rules(V) class L2Inner(object): def __init__(self): self.A = assemble(TrialFunction(V) * TestFunction(V) * dx(rule=qr_x), mat_type="matfree") self.Ap = as_backend_type(self.A).mat() def eval(self, _u, _v): upet = as_backend_type(_u).vec() vpet = as_backend_type(_v).vec() A_u = self.Ap.createVecLeft() self.Ap.mult(upet, A_u) return vpet.dot(A_u) class Objective(ROL.Objective): def __init__(self, inner_product): ROL.Objective.__init__(self) self.inner_product = inner_product self.p_guess = None self.misfit = None def value(self, x, tol): """Compute the functional""" self.p_guess, p_guess_recv = spyro.solvers.forward( model, mesh, comm, vp_guess, sources, wavelet, receivers, output=False, ) self.misfit = spyro.utils.evaluate_misfit(model, p_guess_recv, p_exact_recv) J = spyro.utils.compute_functional(model, self.misfit) return J def gradient(self, g, x, tol): dJ = spyro.solvers.gradient( model, mesh, comm, vp_guess, receivers, self.p_guess, self.misfit, ) g.scale(0) g.vec += dJ def update(self, x, flag, iteration): vp_guess.assign(Function(V, x.vec, name="velocity")) paramsDict = { "Step": { "Line Search": { "Descent Method": { "Type": "Quasi-Newton Method" } }, "Type": "Line Search", }, "Status Test": { "Gradient Tolerance": 1e-12, "Iteration Limit": 20 }, } params = ROL.ParameterList(paramsDict, "Parameters") inner_product = L2Inner() obj = Objective(inner_product) u = Function(V).assign(vp_guess) opt = FeVector(u.vector(), inner_product) d = Function(V) x, y = SpatialCoordinate(mesh) # d.interpolate(sin(x * pi) * sin(y * pi)) d.vector()[:] = np.random.rand(V.dim()) # d.assign(0.1) d = FeVector(d.vector(), inner_product) # check the gradient using d model pertubation 4 iterations and 2nd order test obj.checkGradient(opt, d, 4, 2)
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()
# and on the -x and -y sides of the domain, the PML region must have negative coordinates. mesh.coordinates.dat.data[:, 0] -= 3.0 mesh.coordinates.dat.data[:, 1] -= 1.0 mesh.coordinates.dat.data[:, 2] -= 1.0 comm = spyro.utils.mpi_init(model) element = spyro.domains.space.FE_method( mesh, model["opts"]["method"], model["opts"]["degree"] ) V = FunctionSpace(mesh, element) if comm.comm.rank == 0: print("There are " + str(V.dim()) + " degrees of freedom", flush=True) sources = spyro.Sources(model, mesh, V, comm).create() receivers = spyro.Receivers(model, mesh, V, comm).create() vp = Function(V, name="velocity").assign(1.5) t1 = time.time() p_field, p_at_recv = spyro.solvers.Leapfrog( model, mesh, comm, vp, sources, receivers, output=False, )
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