def __init__(self, mesh, conditions, timestepping, params, output, solver_params): self.timestepping = timestepping self.timestep = timestepping.timestep self.timescale = timestepping.timescale self.params = params if output is None: raise RuntimeError("You must provide a directory name for dumping results") else: self.output = output self.outfile = File(output.dirname) self.dump_count = 0 self.dump_freq = output.dumpfreq self.solver_params = solver_params self.mesh = mesh self.conditions = conditions if conditions.steady_state == True: self.ind = 1 else: self.ind = 1 family = conditions.family self.x, self.y = SpatialCoordinate(mesh) self.n = FacetNormal(mesh) self.V = VectorFunctionSpace(mesh, family, conditions.order + 1) self.U = FunctionSpace(mesh, family, conditions.order + 1) self.U1 = FunctionSpace(mesh, 'DG', conditions.order) self.S = TensorFunctionSpace(mesh, 'DG', conditions.order) self.D = FunctionSpace(mesh, 'DG', 0) self.W1 = MixedFunctionSpace([self.V, self.S]) self.W2 = MixedFunctionSpace([self.V, self.U1, self.U1]) self.W3 = MixedFunctionSpace([self.V, self.S, self.U1, self.U1])
def create_output_file(name, comm, source_num): if io.is_owner(comm, source_num): outfile = File( os.getcwd() + "/results/shots_" + str(source_num) + "_ensemble_" + str(comm.ensemble_comm.rank) + name, comm=comm.comm, ) return outfile
def export_fun(fname, *funs): """ Export a list of functions to a VTK file (.pvd). Arguments --------- fname : str Filename to export to *funs : firedrake.Function Any number of functions to export """ outfile = File(fname) outfile.write(*funs)
def solve(self, file_path='ttip_result/solution.pvd'): """ Setup and solve the nonlinear problem. Save value to file given. Any additional keyword arguments are passed to the iteration method. Args: file_path (string, optional): The path to save the pvd file to. vtk files will be generated in the same directory as the pvd. It is recommended that this is a separate drectory per run. Defaults to 'TTiP_result/solution.pvd'. """ F = self.problem.a - self.problem.L steady_state = self.is_steady_state() if isinstance(self.problem, BoundaryMixin): var_prob = NonlinearVariationalProblem(F, self.u, bcs=self.problem.bcs) else: var_prob = NonlinearVariationalProblem(F, self.u) solver = NonlinearVariationalSolver(problem=var_prob, solver_parameters=self.params) outfile = File(file_path) outfile.write(self.u, target_degree=1, target_continuity=H1) if steady_state: solver.solve() outfile.write(self.u, target_degree=1, target_continuity=H1) else: self.problem.T_.assign(self.u) last_perc = 0 for i in range(self.problem.steps): solver.solve() perc = int(100 * (i + 1) / self.problem.steps) if perc > last_perc: print(f'{perc}%') last_perc = perc self.problem.T_.assign(self.u) outfile.write(self.u, target_degree=1, target_continuity=H1)
def regularization_form(r): mesh = UnitSquareMesh(2 ** r, 2 ** r) x = SpatialCoordinate(mesh) S = VectorFunctionSpace(mesh, "CG", 1) beta = 4.0 reg_solver = RegularizationSolver(S, mesh, beta=beta, gamma=0.0, dx=dx) # Exact solution with free Neumann boundary conditions for this domain u_exact = Function(S) u_exact_component = cos(x[0] * pi * 2) * cos(x[1] * pi * 2) u_exact.interpolate(as_vector((u_exact_component, u_exact_component))) f = Function(S) theta = TestFunction(S) f_component = (1 + beta * 8 * pi * pi) * u_exact_component f.interpolate(as_vector((f_component, f_component))) rhs_form = inner(f, theta) * dx velocity = Function(S) rhs = assemble(rhs_form) reg_solver.solve(velocity, rhs) File("solution_vel_unitsquare.pvd").write(velocity) return norm(project(u_exact - velocity, S))
# Pressure update a2 = inner(grad(p), grad(q)) * dx L2 = -(1 / k) * div(u1) * q * dx # Velocity update a3 = inner(u, v) * dx L3 = inner(u1, v) * dx - k * inner(grad(p1), v) * dx # Assemble matrices A1 = assemble(a1) A2 = assemble(a2) A3 = assemble(a3) # Create files for storing solution ufile = File("results/velocity.pvd") pfile = File("results/pressure.pvd") # Time-stepping t = dt numSteps = int(T / dt) for i in range(numSteps): # Update pressure boundary condition # Compute tentative velocity step # begin("Computing tentative velocity") b1 = assemble(L1) [bc.apply(A1, b1) for bc in bcu]
def setup_dump(self, t, tmax, pickup=False): """ Setup dump files Check for existence of directory so as not to overwrite output files Setup checkpoint file :arg tmax: model stop time :arg pickup: recover state from the checkpointing file if true, otherwise dump and checkpoint to disk. (default is False). """ if any([ self.output.dump_vtus, self.output.dumplist_latlon, self.output.dump_diagnostics, self.output.point_data, self.output.checkpoint and not pickup ]): # setup output directory and check that it does not already exist self.dumpdir = path.join("results", self.output.dirname) running_tests = '--running-tests' in sys.argv or "pytest" in self.output.dirname if self.mesh.comm.rank == 0: if not running_tests and path.exists( self.dumpdir) and not pickup: raise IOError("results directory '%s' already exists" % self.dumpdir) else: if not running_tests: makedirs(self.dumpdir) if self.output.dump_vtus: # setup pvd output file outfile = path.join(self.dumpdir, "field_output.pvd") self.dumpfile = File(outfile, project_output=self.output.project_fields, comm=self.mesh.comm) # make list of fields to dump self.to_dump = [ f for f in self.fields if f.name() in self.fields.to_dump ] # make dump counter self.dumpcount = itertools.count() # if there are fields to be dumped in latlon coordinates, # setup the latlon coordinate mesh and make output file if len(self.output.dumplist_latlon) > 0: mesh_ll = get_latlon_mesh(self.mesh) outfile_ll = path.join(self.dumpdir, "field_output_latlon.pvd") self.dumpfile_ll = File(outfile_ll, project_output=self.output.project_fields, comm=self.mesh.comm) # make functions on latlon mesh, as specified by dumplist_latlon self.to_dump_latlon = [] for name in self.output.dumplist_latlon: f = self.fields(name) field = Function(functionspaceimpl.WithGeometry.create( f.function_space(), mesh_ll), val=f.topological, name=name + '_ll') self.to_dump_latlon.append(field) # we create new netcdf files to write to, unless pickup=True, in # which case we just need the filenames if self.output.dump_diagnostics: diagnostics_filename = self.dumpdir + "/diagnostics.nc" self.diagnostic_output = DiagnosticsOutput(diagnostics_filename, self.diagnostics, self.output.dirname, self.mesh.comm, create=not pickup) if len(self.output.point_data) > 0: # set up point data output pointdata_filename = self.dumpdir + "/point_data.nc" ndt = int(tmax / float(self.dt)) self.pointdata_output = PointDataOutput(pointdata_filename, ndt, self.output.point_data, self.output.dirname, self.fields, self.mesh.comm, self.output.tolerance, create=not pickup) # make point data dump counter self.pddumpcount = itertools.count() # set frequency of point data output - defaults to # dumpfreq if not set by user if self.output.pddumpfreq is None: self.output.pddumpfreq = self.output.dumpfreq # if we want to checkpoint and are not picking up from a previous # checkpoint file, setup the checkpointing if self.output.checkpoint: if not pickup: self.chkpt = DumbCheckpoint(path.join(self.dumpdir, "chkpt"), mode=FILE_CREATE) # make list of fields to pickup (this doesn't include # diagnostic fields) self.to_pickup = [ f for f in self.fields if f.name() in self.fields.to_pickup ] # if we want to checkpoint then make a checkpoint counter if self.output.checkpoint: self.chkptcount = itertools.count() # dump initial fields self.dump(t)
'pc_python_type': 'firedrake.HybridizationPC', 'hybridization': { 'ksp_type': 'preonly', 'pc_type': 'lu', 'pc_factor_mat_solver_type': 'mumps' } } uD_problem = LinearVariationalProblem(lhs(eqn), rhs(eqn), xd) uD_solver = LinearVariationalSolver(uD_problem, solver_parameters=params) if COMM_WORLD.Get_rank() == 0: print("Finished setting up solvers at ", ctime()) # Setup output outfile = File('{0}.pvd'.format(fname)) field_output = [un, eta_out, En, vortn, qn, q2Dn] # Create latlon version of output def get_latlon_mesh(mesh): """Build 2D projected mesh of spherical mesh""" crds_orig = mesh.coordinates mesh_dg_fs = VectorFunctionSpace(mesh, "DG", 1) crds_dg = Function(mesh_dg_fs) crds_latlon = Function(mesh_dg_fs) par_loop( """ for (int i=0; i<3; i++) { for (int j=0; j<3; j++) { dg[i][j] = cg[i][j];
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 nlspace_solve(problem: InfDimProblem, params=None, results=None, descent_output_dir=None): """ Solve the optimization problem min J(phi) phi in V under the constraints g_i(phi)=0 for all i=0..p-1 h_i(phi)<=0 for all i=0..q-1 Usage ----- results=nlspace_solve(problem: InfDimProblem, params: dict, results:dict) Inputs ------ problem : an `~InfDimProblem` object corresponding to the optimization problem above. params : (optional) a dictionary containing algorithm parameters (see below). results : (optional) a previous output of the nlspace_solve` function. The optimization will keep going from the last input of the dictionary `results['phi'][-1]`. Useful to restart an optimization after an interruption. descent_output_dir : Plot the descent direction in the given directory Output ------ results : dictionary containing results['J'] : values of the objective function along the path (J(phi_0),...,J(phi_n)) results['G'] : equality constraint values (G(phi_0),...,G(phi_n)) results['H'] : inequality constraints values (H(phi_0),...,H(phi_n)) results['muls'] : lagrange multiplier values (mu(phi_0),...,mu(phi_n)) Optional algorithm parameters ----------------------------- params['alphaJ'] : (default 1) scaling coefficient for the null space step xiJ decreasing the objective function params['alphaC'] : (default 1) scaling coefficient for the Gauss Newton step xiC decreasing the violation of the constraints params['alphas'] : (optional) vector of dimension problem.nconstraints + problem.nineqconstraints containing proportionality coefficients scaling the Gauss Newton direction xiC for each of the constraints params['debug'] : Tune the verbosity of the output (default 0) Set param['debug']=-1 to display only the final result Set param['debug']=-2 to remove any output params['dt'] : (default : `1.0`). Pseudo time-step expressed in a time unit. Used to modulate the optimization convergence/oscillatory behavior. params['hmin'] : (default : `1.0`). Mesh minimum length. TODO Replace this for dt in the calculation of the tolerances `eps` params['K']: tunes the distance at which inactive inequality constraints are felt. Constraints are felt from a distance K*params['dt'] params['maxit'] : Maximal number of iterations (default : 4000) params['maxtrials']: (default 3) number of trials in between time steps until the merit function decreases params['tol'] : (default 1e-7) Algorithm stops when ||phi_{n+1}-phi_n||<params['tol'] or after params['maxit'] iterations. params['tol_merit'] : (default 0) a new iterate phi_{n+1} is accepted if merit(phi_{n+1})<(1+sign(merit(phi_n)*params['tol_merit']))*merit(phi_n) params['tol_qp'] : (default 1e-20) the tolerance for the qp solver cvxopt params['show_progress_qp'] : (default False) If true, then the output of cvxopt will be displayed between iterations. params['monitor_time'] : (default False) If true, then the output of the time taken between optimization iterations. """ params = set_parameters(params) alphas = np.asarray( params.get( "alphas", [1] * (len(problem.eqconstraints) + len(problem.ineqconstraints)), )) if descent_output_dir: descent_pvd = File(f"{descent_output_dir}/descent_direction.pvd") results = { "phi": [], "J": [], "G": [], "H": [], "muls": [], "merit": [], } phi = problem.x0() (J, G, H) = problem.eval(phi) normdx = 1 # current value for x_{n+1}-x_n new_phi = Function(phi.function_space()) orig_phi = Function(phi.function_space()) while normdx > params["tol"] and len(results["J"]) < params["maxit"]: with MPITimer(phi.comm) as timings: results["J"].append(J) results["G"].append(G) results["H"].append(H) if problem.accept(): break it = len(results["J"]) - 1 display("\n", params["debug"], 1) display( f"{it}. J=" + format(J, ".4g") + " " + "G=[" + ",".join(format(phi, ".4g") for phi in G[:10]) + "] " + "H=[" + ",".join(format(phi, ".4g") for phi in H[:10]) + "] " + " ||dx||_V=" + format(normdx, ".4g"), params["debug"], 0, ) # Returns the gradients (in the primal space). They are # firedrake.Function's (dJ, dG, dH) = problem.eval_gradients(phi) dC = dG + dH H = np.asarray(H) G = np.asarray(G) C = np.concatenate((G, H)) # Obtain the tolerances for the inequality constraints and the indices # for the violated constraints eps = getEps( dC, problem.n_eqconstraints, params["dt"], params["K"], norm_type=params["normalisation_norm"], ) tildeEps = getTilde(C, problem.n_eqconstraints, eps=eps) print(f"eps: {eps}") # Obtain the violated contraints tilde = getTilde(C, problem.n_eqconstraints) p_matrix = p_matrix_eval(dC, tildeEps) q_vector = q_vector_eval(dJ, dC, tildeEps) qp_results = solve_dual_problem( p_matrix, q_vector, tildeEps, problem.n_eqconstraints, show_progress_qp=params["show_progress_qp"], tol_qp=params["tol_qp"], ) muls = np.zeros(len(C)) oldmuls = np.zeros(len(C)) hat = np.asarray([False] * len(C)) if qp_results: muls[tildeEps] = np.asarray(qp_results["x"]).flatten() oldmuls = muls.copy() hat = np.asarray([True] * len(C)) hat[problem.n_eqconstraints:] = (muls[problem.n_eqconstraints:] > 30 * params["tol_qp"]) if params.get("disable_dual", False): hat = tildeEps dCdCT = dCdCT_eval(dC, hat) dCdCTinv = invert_dCdCT(dCdCT, params["debug"]) muls = np.zeros(len(C)) dCdJ = dCdJ_eval(dJ, dC, hat) muls[hat] = -dCdCTinv.dot(dCdJ[hat]) if not np.all(muls[problem.n_eqconstraints:] >= 0): display( "Warning, the active set has not been predicted " + "correctly Using old lagrange multipliers", params["debug"], level=1, color="orange_4a", ) hat = np.asarray([True] * len(C)) muls = oldmuls.copy() results["muls"].append(muls) display(f"Lagrange multipliers: {muls[:10]}", params["debug"], level=5) xiJ = xiJ_eval(dJ, dC, muls, hat) # Set of constraints union of active and new violated constraints. indicesEps = np.logical_or(tilde, hat) dCdCT = dCdCT_eval(dC, indicesEps) dCtdCtTinv = invert_dCdCT(dCdCT, params["debug"]) xiC = xiC_eval(C, dC, dCtdCtTinv, alphas, indicesEps) # TODO Consider this? AC = min(0.9, alphaC * dt / max(compute_norm(xiC), 1e-9)) AJ = params["alphaJ"] AC = params["alphaC"] # Make updates with merit function if xiC: problem.delta_x.assign( Constant(-AJ) * xiJ - Constant(AC) * xiC) else: problem.delta_x.assign(Constant(-AJ) * xiJ) normdx = fd.norm(problem.delta_x) merit_eval_new = partial(merit_eval, muls, indicesEps, dCtdCtTinv) merit = merit_eval_new(AJ, J, AC, C) results["merit"].append(merit) if len(results["merit"]) > 3: print( f"Merit oscillation: {(results['merit'][-1] - results['merit'][-2]) * (results['merit'][-2] - results['merit'][-3])}" ) if descent_output_dir: descent_pvd.write(problem.delta_x) orig_phi.assign(phi) new_phi, newJ, newG, newH = line_search( problem, orig_phi, new_phi, merit_eval_new, merit, AJ, AC, dt=params["dt"], maxtrials=params["maxtrials"], tol_merit=params["tol_merit"], debug=params["debug"], ) phi.assign(new_phi) (J, G, H) = (newJ, newG, newH) if params["monitor_time"]: print( f"Max time per iteration: {timings.max_time}, min time per iteration: {timings.min_time}" ) results["J"].append(J) results["G"].append(G) results["H"].append(H) display("\n", params["debug"], -1) display("Optimization completed.", params["debug"], -1) return results
str(LC1), "-setnumber", "lc2", str(LC2), "mesh/hexa.geo" ]) permittivity_dict = {1: 1, 2: 11.8, 3: 1} s = np.array([1, 2]) p = np.array([-2, 1]) k0L = np.pi print("Isotropic Scattering with permittivity {} and n {}".format( permittivity_dict, i)) problem = IsotropicScattering(mesh_file, permittivity_dict, k0L) pw = PlaneWave(s, p) E_isotropic = problem.solve(pw) File(f"results/isotropic_{i}.pvd").write(E_isotropic) phi, FF_isotropic = problem.get_far_field(E_isotropic, FAR_FIELD_POINTS) np.save(f"results/ff_isotropic-{i}.npy", FF_isotropic) epsilon = [[5.46549124, 0], [0, 5.7717177]] permittivity_dict = {1: epsilon, 2: epsilon, 3: np.identity(2)} print("Anisotropic Scattering with permittivity {} and n {}".format( permittivity_dict, i)) problem = AnisotropicScattering(problem.mesh, permittivity_dict, k0L) E_anisotropic = problem.solve(pw) File(f"results/anisotropic_{i}.pvd").write(E_anisotropic) _, FF_anisotropic = problem.get_far_field(E_anisotropic,
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
def __init__(self, prognostic_variables, diagnostic_variables, simulation_parameters, peakon_equations=None, diagnostic_values=None): self.ndump = simulation_parameters['ndump'][-1] self.field_ndump = simulation_parameters['field_ndump'][-1] self.prognostic_variables = prognostic_variables self.diagnostic_variables = diagnostic_variables self.simulation_parameters = simulation_parameters self.peakon_equations = peakon_equations file_name = simulation_parameters['file_name'][-1] dirname = simulation_parameters['dirname'][-1] self.data_file = Dataset(file_name, 'a') # set up things for dumping diagnostics if diagnostic_values is not None: if isinstance(diagnostic_values, str): dimensions = self.data_file[diagnostic_values].dimensions else: if diagnostic_values[0] != 'mu': dimensions = self.data_file[ diagnostic_values[0]].dimensions else: dimensions = self.data_file[diagnostic_values[0] + '_' + str(0)].dimensions index_list = [] variable_list = [] for dimension in dimensions: if dimension not in ('time', 'x'): variable_list.append(dimension) index_list.append(simulation_parameters[dimension][0]) self.index_slices = [slice(index, index + 1) for index in index_list] self.t_idx = 0 self.diagnostic_values = diagnostic_values self.list_of_peakon_diagnostics = [ 'peakon_loc', 'peakon_min_du', 'peakon_max_du', 'peakon_min_du_loc', 'peakon_max_du_loc', 'peakon_max_u', 'peakon_mu', 'peakon_nu' ] # set up things for dumping fields if self.field_ndump > 0: field_file_name = dirname + '/fields' for dimension, index in zip(variable_list, index_list): field_file_name += '_' + str(dimension) + str(index) field_file_name += '_output.pvd' self.field_file = File(field_file_name) prognostic_variables = [ value for value in self.prognostic_variables.fields.values() ] diagnostic_variables = [ value for value in self.diagnostic_variables.dumpfields.values() ] self.dumpfields = prognostic_variables + diagnostic_variables self.out_string = '' for key, value in simulation_parameters.items(): if len(value) > 1: self.out_string += str(key) + ' = %s, ' % str(value[0]) # write initial wallclock time self.data_file['wallclock_time'][ [slice(0, 1)] + self.index_slices] = datetime.now().timestamp() # set up coordinate field if self.simulation_parameters['store_coordinates'][-1]: self.data_file[ 'x'][:] = self.diagnostic_variables.coords.dat.data[:]
def setup_dump(self, tmax, pickup=False): """ Setup dump files Check for existence of directory so as not to overwrite output files Setup checkpoint file :arg tmax: model stop time :arg pickup: recover state from the checkpointing file if true, otherwise dump and checkpoint to disk. (default is False). """ self.dumpdir = path.join("results", self.output.dirname) outfile = path.join(self.dumpdir, "field_output.pvd") if self.mesh.comm.rank == 0 and "pytest" not in self.output.dirname \ and path.exists(self.dumpdir) and not pickup: raise IOError("results directory '%s' already exists" % self.dumpdir) self.dumpcount = itertools.count() self.dumpfile = File(outfile, project_output=self.output.project_fields, comm=self.mesh.comm) if self.output.checkpoint and not pickup: self.chkpt = DumbCheckpoint(path.join(self.dumpdir, "chkpt"), mode=FILE_CREATE) # make list of fields to dump self.to_dump = [field for field in self.fields if field.dump] # if there are fields to be dumped in latlon coordinates, # setup the latlon coordinate mesh and make output file if len(self.output.dumplist_latlon) > 0: mesh_ll = get_latlon_mesh(self.mesh) outfile_ll = path.join(self.dumpdir, "field_output_latlon.pvd") self.dumpfile_ll = File(outfile_ll, project_output=self.output.project_fields, comm=self.mesh.comm) # make list of fields to pickup (this doesn't include diagnostic fields) self.to_pickup = [field for field in self.fields if field.pickup] # make functions on latlon mesh, as specified by dumplist_latlon self.to_dump_latlon = [] for name in self.output.dumplist_latlon: f = self.fields(name) field = Function(functionspaceimpl.WithGeometry( f.function_space(), mesh_ll), val=f.topological, name=name + '_ll') self.to_dump_latlon.append(field) # we create new netcdf files to write to, unless pickup=True, in # which case we just need the filenames if self.output.dump_diagnostics: diagnostics_filename = self.dumpdir + "/diagnostics.nc" self.diagnostic_output = DiagnosticsOutput(diagnostics_filename, self.diagnostics, self.output.dirname, create=not pickup) if len(self.output.point_data) > 0: pointdata_filename = self.dumpdir + "/point_data.nc" ndt = int(tmax / self.timestepping.dt) self.pointdata_output = PointDataOutput(pointdata_filename, ndt, self.output.point_data, self.output.dirname, self.fields, create=not pickup)
def do_simulation_loop(N, variable_parameters, simulation_parameters, diagnostics=None, fields_to_output=None, expected_u=False): """ A recursive strategy for setting up a variable number of for loops for the experiment. :arg N: the level of loop. :arg variable_parameters: an OrderedDict of the parameters to be varied. :arg simulation_parameters: a dict storing the parameters for that simulation. :arg diagnostics: a list of diagnostic values to be output. :arg fields_to_output: a list of fields to be output. """ # we do the loop in reverse order to get the resolution loop on the outside M = len(variable_parameters) key = list(variable_parameters.items())[M - N][0] have_setup = False # we must turn the ordered dict into a list to iterate through it for index, value in enumerate( list(variable_parameters.items())[M - N][1][1]): simulation_parameters[key] = (index, value) # make mesh if loop is a resolution loop if key == 'resolution': mesh = PeriodicIntervalMesh(value, simulation_parameters['Ld'][-1]) simulation_parameters['mesh'] = (mesh, ) # do recursion if we aren't finished yet if N > 1: do_simulation_loop(N - 1, variable_parameters, simulation_parameters, diagnostics=diagnostics, fields_to_output=fields_to_output, expected_u=expected_u) # finally do simulation elif N == 1: if expected_u: this_u = simulation(simulation_parameters, diagnostic_values=diagnostics, fields_to_output=fields_to_output, expected_u=True) if have_setup: Eu.assign(counter * Eu + this_u) counter.assign(counter + 1) Eu.assign(Eu / counter) else: scheme = simulation_parameters['scheme'][-1] mesh = simulation_parameters['mesh'][-1] prognostic_variables = PrognosticVariables(scheme, mesh) Eu = Function(prognostic_variables.Vu, name='expected u').assign(this_u) counter = Constant(1.0) have_setup = True else: simulation(simulation_parameters, diagnostic_values=diagnostics, fields_to_output=fields_to_output) if expected_u: expected_u_file = File(simulation_parameters['dirname'][-1] + '/expected_u.pvd') expected_u_file.write(Eu)
"num_receivers": len(receivers), "receiver_locations": receivers, } model["timeaxis"] = { "t0": 0.0, # Initial time for event "tf": 4.00, # 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"], ) t1 = time.time() p, p_r = spyro.solvers.forward(model, mesh, comm, vp, sources, wavelet, receivers,
def run(steady=False): """ solve CdT/dt = S + div(k*grad(T)) => C*v*(dT/dt)/k*dx - S*v/k*dx + grad(v)*grad(T)*dx = v*dot(grad(T), n)*ds """ steps = 250 dt = 1e-10 timescale = (0, steps * dt) if steady: print('Running steady state.') else: print(f'Running with time step {dt:.2g}s on time interval: ' f'{timescale[0]:.2g}s - {timescale[1]:.2g}s') dt_invc = Constant(1 / dt) extent = [40e-6, 40e-6, 40e-6] mesh = BoxMesh(20, 20, 20, *extent) V = FunctionSpace(mesh, 'CG', 1) print(V.dim()) T = Function(V) # temperature at time i+1 (electron for now) T_ = Function(V) # temperature at time i v = TestFunction(V) # test function S = create_S(mesh, V, extent) C = create_heat_capacity(mesh, V, extent) k = create_conductivity(mesh, V, T) set_initial_value(mesh, T_, extent) # Mass matrix section M = C * T * dt_invc * v * dx M_ = C * T_ * dt_invc * v * dx # Stiffness matrix section A = k * dot(grad(T), grad(v)) * dx # function section f = S * v * dx # boundaries bcs, R, b = create_dirichlet_bounds(mesh, V, T, v, k, g=100, boundary=[1, 2, 3, 4, 5, 6]) # bcs += create_dirichlet_bounds(mesh, V, T, v, k, 500, [6])[0] # bcs, R, b = create_robin_bounds(mesh, T, v, k, 1e8/(100), 1e8) if steady: steps = 1 a = A + R L = f + b else: a = M + A + R L = M_ + f + b prob = NonlinearVariationalProblem(a - L, T, bcs=bcs) solver = NonlinearVariationalSolver(prob, solver_parameters=SOLVE_PARAMS) T.assign(T_) timestamp = datetime.now().strftime("%d-%b-%Y-%H-%M-%S") outfile = File(f'{timestamp}/first_output.pvd') outfile.write(T_, target_degree=1, target_continuity=H1) last_perc = 0 for i in range(steps): solver.solve() perc = int(100 * (i + 1) / steps) if perc > last_perc: print(f'{perc}%') last_perc = perc T_.assign(T) outfile.write(T_, target_degree=1, target_continuity=H1)