def test_isentropic_vortex(actx_factory, order): """Advance the 2D isentropic vortex case in time with non-zero velocities using an RK4 timestepping scheme. Check the advanced field values against the exact/analytic expressions. This tests all parts of the Euler module working together, with results converging at the expected rates vs. the order. """ actx = actx_factory() dim = 2 from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() for nel_1d in [16, 32, 64]: from meshmode.mesh.generation import ( generate_regular_rect_mesh, ) mesh = generate_regular_rect_mesh(a=(-5.0, ) * dim, b=(5.0, ) * dim, nelements_per_axis=(nel_1d, ) * dim) exittol = 1.0 t_final = 0.001 cfl = 1.0 vel = np.zeros(shape=(dim, )) orig = np.zeros(shape=(dim, )) vel[:dim] = 1.0 dt = .0001 initializer = Vortex2D(center=orig, velocity=vel) casename = "Vortex" boundaries = {BTAG_ALL: PrescribedBoundary(initializer)} eos = IdealSingleGas() t = 0 flowparams = { "dim": dim, "dt": dt, "order": order, "time": t, "boundaries": boundaries, "initializer": initializer, "eos": eos, "casename": casename, "mesh": mesh, "tfinal": t_final, "exittol": exittol, "cfl": cfl, "constantcfl": False, "nstatus": 0 } maxerr = _euler_flow_stepper(actx, flowparams) eoc_rec.add_data_point(1.0 / nel_1d, maxerr) logger.info(f"Error for (dim,order) = ({dim},{order}):\n" f"{eoc_rec}") assert (eoc_rec.order_estimate() >= order - 0.5 or eoc_rec.max_error() < 1e-11)
def test_lump_rhs(actx_factory, dim, order): """Tests the inviscid rhs using the non-trivial 1, 2, and 3D mass lump case against the analytic expressions of the RHS. Checks several different orders and refinement levels to check error behavior. """ actx = actx_factory() tolerance = 1e-10 maxxerr = 0.0 from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() for nel_1d in [4, 8, 12]: from meshmode.mesh.generation import ( generate_regular_rect_mesh, ) mesh = generate_regular_rect_mesh( a=(-5, ) * dim, b=(5, ) * dim, n=(nel_1d, ) * dim, ) logger.info(f"Number of elements: {mesh.nelements}") discr = EagerDGDiscretization(actx, mesh, order=order) nodes = thaw(actx, discr.nodes()) # Init soln with Lump and expected RHS = 0 center = np.zeros(shape=(dim, )) velocity = np.zeros(shape=(dim, )) lump = Lump(center=center, velocity=velocity) lump_soln = lump(0, nodes) boundaries = {BTAG_ALL: PrescribedBoundary(lump)} inviscid_rhs = inviscid_operator(discr, eos=IdealSingleGas(), boundaries=boundaries, q=lump_soln, t=0.0) expected_rhs = lump.exact_rhs(discr, lump_soln, 0) err_max = discr.norm(inviscid_rhs - expected_rhs, np.inf) if err_max > maxxerr: maxxerr = err_max eoc_rec.add_data_point(1.0 / nel_1d, err_max) logger.info(f"Max error: {maxxerr}") message = (f"Error for (dim,order) = ({dim},{order}):\n" f"{eoc_rec}") logger.info(message) assert (eoc_rec.order_estimate() >= order - 0.5 or eoc_rec.max_error() < tolerance)
def test_vortex_rhs(actx_factory, order): """Tests the inviscid rhs using the non-trivial 2D isentropic vortex case configured to yield rhs = 0. Checks several different orders and refinement levels to check error behavior. """ actx = actx_factory() dim = 2 from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() from meshmode.mesh.generation import generate_regular_rect_mesh for nel_1d in [16, 32, 64]: mesh = generate_regular_rect_mesh( a=(-5, ) * dim, b=(5, ) * dim, n=(nel_1d, ) * dim, ) logger.info(f"Number of {dim}d elements: {mesh.nelements}") discr = EagerDGDiscretization(actx, mesh, order=order) nodes = thaw(actx, discr.nodes()) # Init soln with Vortex and expected RHS = 0 vortex = Vortex2D(center=[0, 0], velocity=[0, 0]) vortex_soln = vortex(0, nodes) boundaries = {BTAG_ALL: PrescribedBoundary(vortex)} inviscid_rhs = inviscid_operator(discr, eos=IdealSingleGas(), boundaries=boundaries, q=vortex_soln, t=0.0) err_max = discr.norm(inviscid_rhs, np.inf) eoc_rec.add_data_point(1.0 / nel_1d, err_max) message = (f"Error for (dim,order) = ({dim},{order}):\n" f"{eoc_rec}") logger.info(message) assert (eoc_rec.order_estimate() >= order - 0.5 or eoc_rec.max_error() < 1e-11)
def main(ctx_factory=cl.create_some_context, snapshot_pattern="y0euler-{step:06d}-{rank:04d}.pkl", restart_step=None, use_profiling=False, use_logmgr=False): """Drive the Y0 example.""" from mpi4py import MPI comm = MPI.COMM_WORLD rank = 0 rank = comm.Get_rank() nparts = comm.Get_size() """logging and profiling""" logmgr = initialize_logmgr(use_logmgr, use_profiling, filename="y0euler.sqlite", mode="wu", mpi_comm=comm) cl_ctx = ctx_factory() if use_profiling: queue = cl.CommandQueue( cl_ctx, properties=cl.command_queue_properties.PROFILING_ENABLE) actx = PyOpenCLProfilingArrayContext( queue, allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)), logmgr=logmgr) else: queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue, allocator=cl_tools.MemoryPool( cl_tools.ImmediateAllocator(queue))) #nviz = 500 #nrestart = 500 nviz = 50 nrestart = 10000000 current_dt = 1.0e-7 #t_final = 5.e-7 t_final = 3e-4 dim = 2 order = 1 exittol = 10000000 # do never exit when comparing to exact solution #t_final = 0.001 current_cfl = 1.0 vel_init = np.zeros(shape=(dim, )) vel_inflow = np.zeros(shape=(dim, )) vel_outflow = np.zeros(shape=(dim, )) orig = np.zeros(shape=(dim, )) #vel[0] = 340.0 #vel_inflow[0] = 100.0 # m/s current_t = 0 casename = "y0euler" constant_cfl = False # no internal euler status messages nstatus = 1000000000 checkpoint_t = current_t current_step = 0 # working gas: CO2 # # gamma = 1.289 # MW=44.009 g/mol # cp = 37.135 J/mol-K, # rho= 1.977 kg/m^3 @298K gamma_CO2 = 1.289 R_CO2 = 8314.59 / 44.009 # background # 100 Pa # 298 K # rho = 1.77619667e-3 kg/m^3 # velocity = 0,0,0 rho_bkrnd = 1.77619667e-3 pres_bkrnd = 100 temp_bkrnd = 298 c_bkrnd = math.sqrt(gamma_CO2 * pres_bkrnd / rho_bkrnd) # isentropic shock relations # # lab frame, moving shock # state 1 is behind (downstream) the shock, state 2 is in front (upstream) of the shock mach = 2.0 pressure_ratio = (2. * gamma_CO2 * mach * mach - (gamma_CO2 - 1.)) / (gamma_CO2 + 1.) density_ratio = (gamma_CO2 + 1.) * mach * mach / ( (gamma_CO2 - 1.) * mach * mach + 2.) mach2 = math.sqrt(((gamma_CO2 - 1.) * mach * mach + 2.) / (2. * gamma_CO2 * mach * mach - (gamma_CO2 - 1.))) rho1 = rho_bkrnd pressure1 = pres_bkrnd rho2 = rho1 * density_ratio pressure2 = pressure1 * pressure_ratio velocity1 = 0. velocity2 = -mach * c_bkrnd * (1 / density_ratio - 1) c_shkd = math.sqrt(gamma_CO2 * pressure2 / rho2) vel_inflow[0] = velocity2 timestepper = rk4_step eos = IdealSingleGas(gamma=gamma_CO2, gas_const=R_CO2) bulk_init = Discontinuity(dim=dim, x0=.05, sigma=0.01, rhol=rho2, rhor=rho1, pl=pressure2, pr=pressure1, ul=vel_inflow[0], ur=0.) inflow_init = Lump(dim=dim, rho0=rho2, p0=pressure2, center=orig, velocity=vel_inflow, rhoamp=0.0) outflow_init = Lump(dim=dim, rho0=rho1, p0=pressure1, center=orig, velocity=vel_outflow, rhoamp=0.0) inflow = PrescribedBoundary(inflow_init) outflow = PrescribedBoundary(outflow_init) wall = AdiabaticSlipBoundary() dummy = DummyBoundary() # shock capturing parameters # sonic conditions density_ratio = (gamma_CO2 + 1.) * 1.0 / ((gamma_CO2 - 1.) + 2.) density_star = rho1 * density_ratio shock_thickness = 20 * 0.001 # on the order of 3 elements, should match what is in mesh generator # alpha is ~h/p (spacing/order) #alpha_sc = shock_thickness*abs(velocity1-velocity2)*density_star alpha_sc = 0.1 # sigma is ~p^-4 sigma_sc = -11.0 # kappa is empirical ... kappa_sc = 0.5 print( f"Shock capturing parameters: alpha {alpha_sc}, s0 {sigma_sc}, kappa {kappa_sc}" ) # timestep estimate wave_speed = max(mach2 * c_bkrnd, c_shkd + velocity2) char_len = 0.001 area = char_len * char_len / 2 perimeter = 2 * char_len + math.sqrt(2 * char_len * char_len) h = 2 * area / perimeter dt_est = 1 / (wave_speed * order * order / h) print(f"Time step estimate {dt_est}\n") dt_est_visc = 1 / (wave_speed * order * order / h + alpha_sc * order * order * order * order / h / h) print(f"Viscous timestep estimate {dt_est_visc}\n") from grudge import sym # boundaries = {BTAG_ALL: DummyBoundary} boundaries = { sym.DTAG_BOUNDARY("Inflow"): inflow, sym.DTAG_BOUNDARY("Outflow"): outflow, sym.DTAG_BOUNDARY("Wall"): wall } #local_mesh, global_nelements = create_parallel_grid(comm, #get_pseudo_y0_mesh) # #local_nelements = local_mesh.nelements if restart_step is None: local_mesh, global_nelements = create_parallel_grid(comm, get_mesh) local_nelements = local_mesh.nelements else: # Restart with open(snapshot_pattern.format(step=restart_step, rank=rank), "rb") as f: restart_data = pickle.load(f) local_mesh = restart_data["local_mesh"] local_nelements = local_mesh.nelements global_nelements = restart_data["global_nelements"] assert comm.Get_size() == restart_data["num_parts"] if rank == 0: logging.info("Making discretization") discr = EagerDGDiscretization(actx, local_mesh, order=order, mpi_communicator=comm) nodes = thaw(actx, discr.nodes()) if restart_step is None: if rank == 0: logging.info("Initializing soln.") current_state = bulk_init(0, nodes, eos=eos) else: current_t = restart_data["t"] current_step = restart_step current_state = unflatten( actx, discr.discr_from_dd("vol"), obj_array_vectorize(actx.from_numpy, restart_data["state"])) vis_timer = None if logmgr: logmgr_add_device_name(logmgr, queue) logmgr_add_discretization_quantities(logmgr, discr, eos, dim) #logmgr_add_package_versions(logmgr) logmgr.add_watches([ "step.max", "t_sim.max", "t_step.max", "min_pressure", "max_pressure", "min_temperature", "max_temperature" ]) try: logmgr.add_watches(["memory_usage.max"]) except KeyError: pass if use_profiling: logmgr.add_watches(["pyopencl_array_time.max"]) vis_timer = IntervalTimer("t_vis", "Time spent visualizing") logmgr.add_quantity(vis_timer) #visualizer = make_visualizer(discr, discr.order + 3 #if discr.dim == 2 else discr.order) visualizer = make_visualizer(discr, discr.order) # initname = initializer.__class__.__name__ initname = "pseudoY0" eosname = eos.__class__.__name__ init_message = make_init_message(dim=dim, order=order, nelements=local_nelements, global_nelements=global_nelements, dt=current_dt, t_final=t_final, nstatus=nstatus, nviz=nviz, cfl=current_cfl, constant_cfl=constant_cfl, initname=initname, eosname=eosname, casename=casename) if rank == 0: logger.info(init_message) get_timestep = partial(inviscid_sim_timestep, discr=discr, t=current_t, dt=current_dt, cfl=current_cfl, eos=eos, t_final=t_final, constant_cfl=constant_cfl) def my_rhs(t, state): #return inviscid_operator(discr, eos=eos, boundaries=boundaries, q=state, t=t) return (inviscid_operator( discr, q=state, t=t, boundaries=boundaries, eos=eos) + artificial_viscosity(discr, t=t, r=state, eos=eos, boundaries=boundaries, alpha=alpha_sc, sigma=sigma_sc, kappa=kappa_sc)) def my_checkpoint(step, t, dt, state): write_restart = (check_step(step, nrestart) if step != restart_step else False) if write_restart is True: with open(snapshot_pattern.format(step=step, rank=rank), "wb") as f: pickle.dump( { "local_mesh": local_mesh, "state": obj_array_vectorize(actx.to_numpy, flatten(state)), "t": t, "step": step, "global_nelements": global_nelements, "num_parts": nparts, }, f) #x0=f(time) exact_soln = Discontinuity(dim=dim, x0=.05, sigma=0.00001, rhol=rho2, rhor=rho1, pl=pressure2, pr=pressure1, ul=vel_inflow[0], ur=0., uc=mach * c_bkrnd) return sim_checkpoint(discr=discr, visualizer=visualizer, eos=eos, q=state, vizname=casename, step=step, t=t, dt=dt, nstatus=nstatus, nviz=nviz, exittol=exittol, constant_cfl=constant_cfl, comm=comm, vis_timer=vis_timer, overwrite=True, exact_soln=exact_soln, sigma=sigma_sc, kappa=kappa_sc) if rank == 0: logging.info("Stepping.") (current_step, current_t, current_state) = \ advance_state(rhs=my_rhs, timestepper=timestepper, checkpoint=my_checkpoint, get_timestep=get_timestep, state=current_state, t_final=t_final, t=current_t, istep=current_step, logmgr=logmgr,eos=eos,dim=dim) if rank == 0: logger.info("Checkpointing final state ...") my_checkpoint(current_step, t=current_t, dt=(current_t - checkpoint_t), state=current_state) if current_t - t_final < 0: raise ValueError("Simulation exited abnormally") if logmgr: logmgr.close() elif use_profiling: print(actx.tabulate_profiling_data())
def main(ctx_factory=cl.create_some_context, use_leap=False): """Drive the example.""" cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue, allocator=cl_tools.MemoryPool( cl_tools.ImmediateAllocator(queue))) dim = 1 nel_1d = 24 order = 1 # tolerate large errors; case is unstable exittol = .2 t_final = 0.01 current_cfl = 1.0 current_dt = .0001 current_t = 0 eos = IdealSingleGas() initializer = SodShock1D(dim=dim) casename = "sod1d" boundaries = {BTAG_ALL: PrescribedBoundary(initializer)} constant_cfl = False nstatus = 10 nviz = 10 rank = 0 checkpoint_t = current_t current_step = 0 if use_leap: from leap.rk import RK4MethodBuilder timestepper = RK4MethodBuilder("state") else: timestepper = rk4_step box_ll = -5.0 box_ur = 5.0 from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() from meshmode.mesh.generation import generate_regular_rect_mesh generate_mesh = partial(generate_regular_rect_mesh, a=(box_ll, ) * dim, b=(box_ur, ) * dim, nelements_per_axis=(nel_1d, ) * dim) local_mesh, global_nelements = generate_and_distribute_mesh( comm, generate_mesh) local_nelements = local_mesh.nelements discr = EagerDGDiscretization(actx, local_mesh, order=order, mpi_communicator=comm) nodes = thaw(actx, discr.nodes()) current_state = initializer(nodes) visualizer = make_visualizer(discr) initname = initializer.__class__.__name__ eosname = eos.__class__.__name__ init_message = make_init_message(dim=dim, order=order, nelements=local_nelements, global_nelements=global_nelements, dt=current_dt, t_final=t_final, nstatus=nstatus, nviz=nviz, cfl=current_cfl, constant_cfl=constant_cfl, initname=initname, eosname=eosname, casename=casename) if rank == 0: logger.info(init_message) get_timestep = partial(inviscid_sim_timestep, discr=discr, t=current_t, dt=current_dt, cfl=current_cfl, eos=eos, t_final=t_final, constant_cfl=constant_cfl) def my_rhs(t, state): return euler_operator(discr, cv=state, t=t, boundaries=boundaries, eos=eos) def my_checkpoint(step, t, dt, state): return sim_checkpoint(discr, visualizer, eos, cv=state, exact_soln=initializer, vizname=casename, step=step, t=t, dt=dt, nstatus=nstatus, nviz=nviz, exittol=exittol, constant_cfl=constant_cfl, comm=comm) try: (current_step, current_t, current_state) = \ advance_state(rhs=my_rhs, timestepper=timestepper, checkpoint=my_checkpoint, get_timestep=get_timestep, state=current_state, t=current_t, t_final=t_final) except ExactSolutionMismatch as ex: current_step = ex.step current_t = ex.t current_state = ex.state # if current_t != checkpoint_t: if rank == 0: logger.info("Checkpointing final state ...") my_checkpoint(current_step, t=current_t, dt=(current_t - checkpoint_t), state=current_state) if current_t - t_final < 0: raise ValueError("Simulation exited abnormally")
def main(ctx_factory=cl.create_some_context): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue, allocator=cl_tools.MemoryPool( cl_tools.ImmediateAllocator(queue))) dim = 3 nel_1d = 16 order = 3 exittol = .09 t_final = 0.01 current_cfl = 1.0 vel = np.zeros(shape=(dim, )) orig = np.zeros(shape=(dim, )) vel[:dim] = 1.0 current_dt = .001 current_t = 0 eos = IdealSingleGas() initializer = Lump(numdim=dim, center=orig, velocity=vel) casename = "lump" boundaries = {BTAG_ALL: PrescribedBoundary(initializer)} constant_cfl = False nstatus = 1 nviz = 1 rank = 0 checkpoint_t = current_t current_step = 0 timestepper = rk4_step box_ll = -5.0 box_ur = 5.0 comm = MPI.COMM_WORLD rank = comm.Get_rank() from meshmode.mesh.generation import generate_regular_rect_mesh generate_grid = partial(generate_regular_rect_mesh, a=(box_ll, ) * dim, b=(box_ur, ) * dim, n=(nel_1d, ) * dim) local_mesh, global_nelements = create_parallel_grid(comm, generate_grid) local_nelements = local_mesh.nelements discr = EagerDGDiscretization(actx, local_mesh, order=order, mpi_communicator=comm) nodes = thaw(actx, discr.nodes()) current_state = initializer(0, nodes) visualizer = make_visualizer( discr, discr.order + 3 if discr.dim == 2 else discr.order) initname = initializer.__class__.__name__ eosname = eos.__class__.__name__ init_message = make_init_message(dim=dim, order=order, nelements=local_nelements, global_nelements=global_nelements, dt=current_dt, t_final=t_final, nstatus=nstatus, nviz=nviz, cfl=current_cfl, constant_cfl=constant_cfl, initname=initname, eosname=eosname, casename=casename) if rank == 0: logger.info(init_message) get_timestep = partial(inviscid_sim_timestep, discr=discr, t=current_t, dt=current_dt, cfl=current_cfl, eos=eos, t_final=t_final, constant_cfl=constant_cfl) def my_rhs(t, state): return inviscid_operator(discr, q=state, t=t, boundaries=boundaries, eos=eos) def my_checkpoint(step, t, dt, state): return sim_checkpoint(discr, visualizer, eos, q=state, exact_soln=initializer, vizname=casename, step=step, t=t, dt=dt, nstatus=nstatus, nviz=nviz, exittol=exittol, constant_cfl=constant_cfl, comm=comm) try: (current_step, current_t, current_state) = \ advance_state(rhs=my_rhs, timestepper=timestepper, checkpoint=my_checkpoint, get_timestep=get_timestep, state=current_state, t=current_t, t_final=t_final) except ExactSolutionMismatch as ex: current_step = ex.step current_t = ex.t current_state = ex.state # if current_t != checkpoint_t: if rank == 0: logger.info("Checkpointing final state ...") my_checkpoint(current_step, t=current_t, dt=(current_t - checkpoint_t), state=current_state) if current_t - t_final < 0: raise ValueError("Simulation exited abnormally")
def main(ctx_factory=cl.create_some_context, use_profiling=False, use_logmgr=False, use_leap=False): """Drive the example.""" from mpi4py import MPI comm = MPI.COMM_WORLD logmgr = initialize_logmgr(use_logmgr, filename="vortex.sqlite", mode="wu", mpi_comm=comm) cl_ctx = ctx_factory() if use_profiling: queue = cl.CommandQueue( cl_ctx, properties=cl.command_queue_properties.PROFILING_ENABLE) actx = PyOpenCLProfilingArrayContext( queue, allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)), logmgr=logmgr) else: queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue, allocator=cl_tools.MemoryPool( cl_tools.ImmediateAllocator(queue))) dim = 2 nel_1d = 16 order = 3 exittol = .1 t_final = 0.1 current_cfl = 1.0 vel = np.zeros(shape=(dim, )) orig = np.zeros(shape=(dim, )) vel[:dim] = 1.0 current_dt = .001 current_t = 0 eos = IdealSingleGas() initializer = Vortex2D(center=orig, velocity=vel) casename = "vortex" boundaries = {BTAG_ALL: PrescribedBoundary(initializer)} constant_cfl = False nstatus = 10 nviz = 10 rank = 0 checkpoint_t = current_t current_step = 0 if use_leap: from leap.rk import RK4MethodBuilder timestepper = RK4MethodBuilder("state") else: timestepper = rk4_step box_ll = -5.0 box_ur = 5.0 rank = comm.Get_rank() if dim != 2: raise ValueError("This example must be run with dim = 2.") from meshmode.mesh.generation import generate_regular_rect_mesh generate_mesh = partial(generate_regular_rect_mesh, a=(box_ll, ) * dim, b=(box_ur, ) * dim, nelements_per_axis=(nel_1d, ) * dim) local_mesh, global_nelements = generate_and_distribute_mesh( comm, generate_mesh) local_nelements = local_mesh.nelements discr = EagerDGDiscretization(actx, local_mesh, order=order, mpi_communicator=comm) nodes = thaw(actx, discr.nodes()) current_state = initializer(nodes) vis_timer = None if logmgr: logmgr_add_device_name(logmgr, queue) logmgr_add_device_memory_usage(logmgr, queue) logmgr_add_many_discretization_quantities(logmgr, discr, dim, extract_vars_for_logging, units_for_logging) logmgr.add_watches([ "step.max", "t_step.max", "t_log.max", "min_temperature", "L2_norm_momentum1" ]) try: logmgr.add_watches( ["memory_usage_python.max", "memory_usage_gpu.max"]) except KeyError: pass if use_profiling: logmgr.add_watches(["multiply_time.max"]) vis_timer = IntervalTimer("t_vis", "Time spent visualizing") logmgr.add_quantity(vis_timer) visualizer = make_visualizer(discr) initname = initializer.__class__.__name__ eosname = eos.__class__.__name__ init_message = make_init_message(dim=dim, order=order, nelements=local_nelements, global_nelements=global_nelements, dt=current_dt, t_final=t_final, nstatus=nstatus, nviz=nviz, cfl=current_cfl, constant_cfl=constant_cfl, initname=initname, eosname=eosname, casename=casename) if rank == 0: logger.info(init_message) get_timestep = partial(inviscid_sim_timestep, discr=discr, t=current_t, dt=current_dt, cfl=current_cfl, eos=eos, t_final=t_final, constant_cfl=constant_cfl) def my_rhs(t, state): return euler_operator(discr, cv=state, t=t, boundaries=boundaries, eos=eos) def my_checkpoint(step, t, dt, state): return sim_checkpoint(discr, visualizer, eos, cv=state, exact_soln=initializer, vizname=casename, step=step, t=t, dt=dt, nstatus=nstatus, nviz=nviz, exittol=exittol, constant_cfl=constant_cfl, comm=comm, vis_timer=vis_timer) try: (current_step, current_t, current_state) = \ advance_state(rhs=my_rhs, timestepper=timestepper, checkpoint=my_checkpoint, get_timestep=get_timestep, state=current_state, t=current_t, t_final=t_final, logmgr=logmgr, eos=eos, dim=dim) except ExactSolutionMismatch as ex: current_step = ex.step current_t = ex.t current_state = ex.state # if current_t != checkpoint_t: if rank == 0: logger.info("Checkpointing final state ...") my_checkpoint(current_step, t=current_t, dt=(current_t - checkpoint_t), state=current_state) if current_t - t_final < 0: raise ValueError("Simulation exited abnormally") if logmgr: logmgr.close() elif use_profiling: print(actx.tabulate_profiling_data())
def main(ctx_factory=cl.create_some_context, use_leap=False): """Drive example.""" cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue, allocator=cl_tools.MemoryPool( cl_tools.ImmediateAllocator(queue))) dim = 3 nel_1d = 16 order = 3 exittol = 10.0 t_final = 0.002 current_cfl = 1.0 velocity = np.zeros(shape=(dim, )) velocity[:dim] = 1.0 current_dt = .001 current_t = 0 constant_cfl = False nstatus = 1 nviz = 1 rank = 0 checkpoint_t = current_t current_step = 0 if use_leap: from leap.rk import RK4MethodBuilder timestepper = RK4MethodBuilder("state") else: timestepper = rk4_step box_ll = -5.0 box_ur = 5.0 error_state = 0 from mpi4py import MPI comm = MPI.COMM_WORLD rank = comm.Get_rank() from meshmode.mesh.generation import generate_regular_rect_mesh generate_mesh = partial(generate_regular_rect_mesh, a=(box_ll, ) * dim, b=(box_ur, ) * dim, nelements_per_axis=(nel_1d, ) * dim) local_mesh, global_nelements = generate_and_distribute_mesh( comm, generate_mesh) local_nelements = local_mesh.nelements discr = EagerDGDiscretization(actx, local_mesh, order=order, mpi_communicator=comm) nodes = thaw(actx, discr.nodes()) casename = "uiuc_mixture" # Pyrometheus initialization from mirgecom.mechanisms import get_mechanism_cti mech_cti = get_mechanism_cti("uiuc") sol = cantera.Solution(phase_id="gas", source=mech_cti) pyrometheus_mechanism = pyro.get_thermochem_class(sol)(actx.np) nspecies = pyrometheus_mechanism.num_species eos = PyrometheusMixture(pyrometheus_mechanism) y0s = np.zeros(shape=(nspecies, )) for i in range(nspecies - 1): y0s[i] = 1.0 / (10.0**(i + 1)) spec_sum = sum([y0s[i] for i in range(nspecies - 1)]) y0s[nspecies - 1] = 1.0 - spec_sum # Mixture defaults to STP (p, T) = (1atm, 300K) initializer = MixtureInitializer(dim=dim, nspecies=nspecies, massfractions=y0s, velocity=velocity) boundaries = {BTAG_ALL: PrescribedBoundary(initializer)} nodes = thaw(actx, discr.nodes()) current_state = initializer(x_vec=nodes, eos=eos) visualizer = make_visualizer(discr) initname = initializer.__class__.__name__ eosname = eos.__class__.__name__ init_message = make_init_message(dim=dim, order=order, nelements=local_nelements, global_nelements=global_nelements, dt=current_dt, t_final=t_final, nstatus=nstatus, nviz=nviz, cfl=current_cfl, constant_cfl=constant_cfl, initname=initname, eosname=eosname, casename=casename) if rank == 0: logger.info(init_message) get_timestep = partial(inviscid_sim_timestep, discr=discr, t=current_t, dt=current_dt, cfl=current_cfl, eos=eos, t_final=t_final, constant_cfl=constant_cfl) def my_rhs(t, state): return euler_operator(discr, cv=state, t=t, boundaries=boundaries, eos=eos) def my_checkpoint(step, t, dt, state): global checkpoint_t checkpoint_t = t return sim_checkpoint(discr, visualizer, eos, cv=state, exact_soln=initializer, vizname=casename, step=step, t=t, dt=dt, nstatus=nstatus, nviz=nviz, exittol=exittol, constant_cfl=constant_cfl, comm=comm) try: (current_step, current_t, current_state) = \ advance_state(rhs=my_rhs, timestepper=timestepper, checkpoint=my_checkpoint, get_timestep=get_timestep, state=current_state, t=current_t, t_final=t_final) except ExactSolutionMismatch as ex: error_state = 1 current_step = ex.step current_t = ex.t current_state = ex.state if current_t != checkpoint_t: # This check because !overwrite if rank == 0: logger.info("Checkpointing final state ...") my_checkpoint(current_step, t=current_t, dt=(current_t - checkpoint_t), state=current_state) if current_t - t_final < 0: error_state = 1 if error_state: raise ValueError("Simulation did not complete successfully.")
def main(ctx_factory=cl.create_some_context, snapshot_pattern="y0euler-{step:06d}-{rank:04d}.pkl", restart_step=None, use_profiling=False, use_logmgr=False): """Drive the Y0 example.""" from mpi4py import MPI comm = MPI.COMM_WORLD rank = 0 rank = comm.Get_rank() nparts = comm.Get_size() """logging and profiling""" logmgr = initialize_logmgr(use_logmgr, filename="y0euler.sqlite", mode="wo", mpi_comm=comm) cl_ctx = ctx_factory() if use_profiling: queue = cl.CommandQueue( cl_ctx, properties=cl.command_queue_properties.PROFILING_ENABLE) actx = PyOpenCLProfilingArrayContext( queue, allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)), logmgr=logmgr) else: queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue, allocator=cl_tools.MemoryPool( cl_tools.ImmediateAllocator(queue))) #nviz = 500 #nrestart = 500 nviz = 10 nrestart = 250 #current_dt = 5.0e-8 # stable with euler current_dt = 5.0e-8 # stable with rk4 #current_dt = 4e-7 # stable with lrsrk144 t_final = 5.e-1 dim = 2 order = 1 exittol = .09 #t_final = 0.001 current_cfl = 1.0 current_t = 0 constant_cfl = False nstatus = 10000000000 rank = 0 checkpoint_t = current_t current_step = 0 vel_burned = np.zeros(shape=(dim, )) vel_unburned = np.zeros(shape=(dim, )) # {{{ Set up initial state using Cantera # Use Cantera for initialization # -- Pick up a CTI for the thermochemistry config # --- Note: Users may add their own CTI file by dropping it into # --- mirgecom/mechanisms alongside the other CTI files. from mirgecom.mechanisms import get_mechanism_cti mech_cti = get_mechanism_cti("uiuc") cantera_soln = cantera.Solution(phase_id="gas", source=mech_cti) nspecies = cantera_soln.n_species # Initial temperature, pressure, and mixutre mole fractions are needed to # set up the initial state in Cantera. temp_unburned = 300.0 temp_ignition = 2000.0 # Parameters for calculating the amounts of fuel, oxidizer, and inert species equiv_ratio = 1.0 ox_di_ratio = 0.21 stoich_ratio = 3.0 # Grab the array indices for the specific species, ethylene, oxygen, and nitrogen i_fu = cantera_soln.species_index("C2H4") i_ox = cantera_soln.species_index("O2") i_di = cantera_soln.species_index("N2") x = np.zeros(nspecies) # Set the species mole fractions according to our desired fuel/air mixture x[i_fu] = (ox_di_ratio * equiv_ratio) / (stoich_ratio + ox_di_ratio * equiv_ratio) x[i_ox] = stoich_ratio * x[i_fu] / equiv_ratio x[i_di] = (1.0 - ox_di_ratio) * x[i_ox] / ox_di_ratio # Uncomment next line to make pylint fail when it can't find cantera.one_atm one_atm = cantera.one_atm # pylint: disable=no-member # one_atm = 101325.0 pres_unburned = one_atm # Let the user know about how Cantera is being initilized print(f"Input state (T,P,X) = ({temp_unburned}, {pres_unburned}, {x}") # Set Cantera internal gas temperature, pressure, and mole fractios cantera_soln.TPX = temp_unburned, pres_unburned, x # Pull temperature, total density, mass fractions, and pressure from Cantera # We need total density, and mass fractions to initialize the fluid/gas state. y_unburned = np.zeros(nspecies) can_t, rho_unburned, y_unburned = cantera_soln.TDY can_p = cantera_soln.P # *can_t*, *can_p* should not differ (significantly) from user's initial data, # but we want to ensure that we use exactly the same starting point as Cantera, # so we use Cantera's version of these data. # now find the conditions for the burned gas cantera_soln.equilibrate('TP') temp_burned, rho_burned, y_burned = cantera_soln.TDY pres_burned = cantera_soln.P casename = "flame1d" pyrometheus_mechanism = pyro.get_thermochem_class(cantera_soln)(actx.np) eos = PyrometheusMixture(pyrometheus_mechanism, tguess=temp_unburned) species_names = pyrometheus_mechanism.species_names print(f"Pyrometheus mechanism species names {species_names}") print( f"Unburned state (T,P,Y) = ({temp_unburned}, {pres_unburned}, {y_unburned}" ) print(f"Burned state (T,P,Y) = ({temp_burned}, {pres_burned}, {y_burned}") # use the burned conditions with a lower temperature bulk_init = MixtureDiscontinuity(dim=dim, x0=0.05, sigma=0.01, nspecies=nspecies, tl=temp_ignition, tr=temp_unburned, pl=pres_burned, pr=pres_unburned, ul=vel_burned, ur=vel_unburned, yl=y_burned, yr=y_unburned) inflow_init = MixtureInitializer(dim=dim, nspecies=nspecies, pressure=pres_burned, temperature=temp_ignition, massfractions=y_burned, velocity=vel_burned) outflow_init = MixtureInitializer(dim=dim, nspecies=nspecies, pressure=pres_unburned, temperature=temp_unburned, massfractions=y_unburned, velocity=vel_unburned) inflow = PrescribedBoundary(inflow_init) outflow = PrescribedBoundary(outflow_init) wall = AdiabaticSlipBoundary() dummy = DummyBoundary() from grudge import sym boundaries = { sym.DTAG_BOUNDARY("Inflow"): inflow, sym.DTAG_BOUNDARY("Outflow"): outflow, sym.DTAG_BOUNDARY("Wall"): wall } if restart_step is None: char_len = 0.001 box_ll = (0.0, 0.0) box_ur = (0.25, 0.01) num_elements = (int((box_ur[0] - box_ll[0]) / char_len), int((box_ur[1] - box_ll[1]) / char_len)) from meshmode.mesh.generation import generate_regular_rect_mesh generate_mesh = partial(generate_regular_rect_mesh, a=box_ll, b=box_ur, n=num_elements, boundary_tag_to_face={ "Inflow": ["-x"], "Outflow": ["+x"], "Wall": ["+y", "-y"] }) local_mesh, global_nelements = generate_and_distribute_mesh( comm, generate_mesh) local_nelements = local_mesh.nelements else: # Restart with open(snapshot_pattern.format(step=restart_step, rank=rank), "rb") as f: restart_data = pickle.load(f) local_mesh = restart_data["local_mesh"] local_nelements = local_mesh.nelements global_nelements = restart_data["global_nelements"] assert comm.Get_size() == restart_data["num_parts"] if rank == 0: logging.info("Making discretization") discr = EagerDGDiscretization(actx, local_mesh, order=order, mpi_communicator=comm) nodes = thaw(actx, discr.nodes()) if restart_step is None: if rank == 0: logging.info("Initializing soln.") # for Discontinuity initial conditions current_state = bulk_init(t=0., x_vec=nodes, eos=eos) # for uniform background initial condition #current_state = bulk_init(nodes, eos=eos) else: current_t = restart_data["t"] current_step = restart_step current_state = unflatten( actx, discr.discr_from_dd("vol"), obj_array_vectorize(actx.from_numpy, restart_data["state"])) vis_timer = None if logmgr: logmgr_add_cl_device_info(logmgr, queue) logmgr_add_many_discretization_quantities(logmgr, discr, dim, extract_vars_for_logging, units_for_logging) #logmgr_add_package_versions(logmgr) logmgr.add_watches([ "step.max", "t_sim.max", "t_step.max", "t_log.max", "min_pressure", "max_pressure", "min_temperature", "max_temperature" ]) try: logmgr.add_watches(["memory_usage.max"]) except KeyError: pass if use_profiling: logmgr.add_watches(["pyopencl_array_time.max"]) vis_timer = IntervalTimer("t_vis", "Time spent visualizing") logmgr.add_quantity(vis_timer) visualizer = make_visualizer( discr, discr.order + 3 if discr.dim == 2 else discr.order) # initname = initializer.__class__.__name__ initname = "flame1d" eosname = eos.__class__.__name__ init_message = make_init_message(dim=dim, order=order, nelements=local_nelements, global_nelements=global_nelements, dt=current_dt, t_final=t_final, nstatus=nstatus, nviz=nviz, cfl=current_cfl, constant_cfl=constant_cfl, initname=initname, eosname=eosname, casename=casename) if rank == 0: logger.info(init_message) timestepper = rk4_step #timestepper = lsrk54_step #timestepper = lsrk144_step #timestepper = euler_step get_timestep = partial(inviscid_sim_timestep, discr=discr, t=current_t, dt=current_dt, cfl=current_cfl, eos=eos, t_final=t_final, constant_cfl=constant_cfl) def my_rhs(t, state): # check for some troublesome output types inf_exists = not np.isfinite(discr.norm(state, np.inf)) if inf_exists: if rank == 0: logging.info( "Non-finite values detected in simulation, exiting...") # dump right now sim_checkpoint(discr=discr, visualizer=visualizer, eos=eos, q=state, vizname=casename, step=999999999, t=t, dt=current_dt, nviz=1, exittol=exittol, constant_cfl=constant_cfl, comm=comm, vis_timer=vis_timer, overwrite=True, s0=s0_sc, kappa=kappa_sc) exit() cv = split_conserved(dim=dim, q=state) return (inviscid_operator( discr, q=state, t=t, boundaries=boundaries, eos=eos) + eos.get_species_source_terms(cv)) def my_checkpoint(step, t, dt, state): write_restart = (check_step(step, nrestart) if step != restart_step else False) if write_restart is True: with open(snapshot_pattern.format(step=step, rank=rank), "wb") as f: pickle.dump( { "local_mesh": local_mesh, "state": obj_array_vectorize(actx.to_numpy, flatten(state)), "t": t, "step": step, "global_nelements": global_nelements, "num_parts": nparts, }, f) cv = split_conserved(dim, state) reaction_rates = eos.get_production_rates(cv) viz_fields = [("reaction_rates", reaction_rates)] return sim_checkpoint(discr=discr, visualizer=visualizer, eos=eos, q=state, vizname=casename, step=step, t=t, dt=dt, nstatus=nstatus, nviz=nviz, exittol=exittol, constant_cfl=constant_cfl, comm=comm, vis_timer=vis_timer, overwrite=True, viz_fields=viz_fields) if rank == 0: logging.info("Stepping.") (current_step, current_t, current_state) = \ advance_state(rhs=my_rhs, timestepper=timestepper, checkpoint=my_checkpoint, get_timestep=get_timestep, state=current_state, t_final=t_final, t=current_t, istep=current_step, logmgr=logmgr,eos=eos,dim=dim) if rank == 0: logger.info("Checkpointing final state ...") my_checkpoint(current_step, t=current_t, dt=(current_t - checkpoint_t), state=current_state) if current_t - t_final < 0: raise ValueError("Simulation exited abnormally") if logmgr: logmgr.close() elif use_profiling: print(actx.tabulate_profiling_data()) exit()
def main(ctx_factory=cl.create_some_context, snapshot_pattern="y0euler-{step:06d}-{rank:04d}.pkl", restart_step=None, use_profiling=False, use_logmgr=False): """Drive the Y0 example.""" from mpi4py import MPI comm = MPI.COMM_WORLD rank = 0 rank = comm.Get_rank() nparts = comm.Get_size() """logging and profiling""" logmgr = initialize_logmgr(use_logmgr, filename="y0euler.sqlite", mode="wo", mpi_comm=comm) cl_ctx = ctx_factory() if use_profiling: queue = cl.CommandQueue(cl_ctx, properties=cl.command_queue_properties.PROFILING_ENABLE) actx = PyOpenCLProfilingArrayContext(queue, allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)), logmgr=logmgr) else: queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue, allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue))) #nviz = 500 #nrestart = 500 nviz = 100 nrestart = 100 #current_dt = 2.5e-8 # stable with euler current_dt = 4e-7 # stable with lrsrk144 t_final = 5.e-1 dim = 3 order = 1 exittol = .09 #t_final = 0.001 current_cfl = 1.0 vel_init = np.zeros(shape=(dim,)) vel_inflow = np.zeros(shape=(dim,)) vel_outflow = np.zeros(shape=(dim,)) orig = np.zeros(shape=(dim,)) orig[0] = 0.83 orig[2] = 0.001 #vel[0] = 340.0 #vel_inflow[0] = 100.0 # m/s current_t = 0 casename = "y0euler" constant_cfl = False nstatus = 10000000000 rank = 0 checkpoint_t = current_t current_step = 0 # working gas: CO2 # # gamma = 1.289 # MW=44.009 g/mol # cp = 37.135 J/mol-K, # rho= 1.977 kg/m^3 @298K gamma_CO2 = 1.289 R_CO2 = 8314.59/44.009 # background # 100 Pa # 298 K # rho = 1.77619667e-3 kg/m^3 # velocity = 0,0,0 rho_bkrnd=1.77619667e-3 pres_bkrnd=100 temp_bkrnd=298 # nozzle inflow # # # stagnation tempertuare 298 K # stagnation pressure 1.5e Pa # # isentropic expansion based on the area ratios between the inlet (r=13e-3m) and the throat (r=6.3e-3) # # MJA, this is calculated offline, add some code to do it for us # # Mach number=0.139145 # pressure=148142 # temperature=297.169 # density=2.63872 # gamma=1.289 # calculate the inlet Mach number from the area ratio nozzleInletRadius = 13.e-3 nozzleThroatRadius = 6.3e-3 nozzleInletArea = math.pi*nozzleInletRadius*nozzleInletRadius nozzleThroatArea = math.pi*nozzleThroatRadius*nozzleThroatRadius inletAreaRatio = nozzleInletArea/nozzleThroatArea def getMachFromAreaRatio(area_ratio, gamma, mach_guess=0.01): error=1.e-8 nextError=1.e8 g=gamma M0=mach_guess while nextError > error: R = ((2/(g+1)+((g-1)/(g+1)*M0*M0))**(((g+1)/(2*g-2))))/M0-area_ratio dRdM = (2*((2/(g+1)+((g-1)/(g+1)*M0*M0))**(((g+1)/(2*g-2))))/ (2*g-2)*(g-1)/(2/(g+1)+((g-1)/(g+1)*M0*M0))- ((2/(g+1)+((g-1)/(g+1)*M0*M0))**(((g+1)/(2*g-2))))* M0**(-2)) M1=M0-R/dRdM nextError=abs(R) M0=M1 return M1 def getIsentropicPressure(mach, P0, gamma): pressure=(1.+(gamma-1.)*0.5*math.pow(mach,2)) pressure=P0*math.pow(pressure,(-gamma/(gamma-1.))) return pressure def getIsentropicTemperature(mach, T0, gamma): temperature=(1.+(gamma-1.)*0.5*math.pow(mach,2)) temperature=T0*math.pow(temperature,-1.0) return temperature inlet_mach = getMachFromAreaRatio(area_ratio = inletAreaRatio, gamma=gamma_CO2, mach_guess = 0.01); # ramp the stagnation pressure start_ramp_pres = 1000 ramp_interval = 5.e-3 t_ramp_start = 1e-5 pres_inflow = getIsentropicPressure(mach=inlet_mach, P0=start_ramp_pres, gamma=gamma_CO2) temp_inflow = getIsentropicTemperature(mach=inlet_mach, T0=298, gamma=gamma_CO2) rho_inflow = pres_inflow/temp_inflow/R_CO2 print(f'inlet Mach number {inlet_mach}') print(f'inlet temperature {temp_inflow}') print(f'inlet pressure {pres_inflow}') end_ramp_pres = 150000 pres_inflow_final = getIsentropicPressure(mach=inlet_mach, P0=end_ramp_pres, gamma=gamma_CO2) print(f'final inlet pressure {pres_inflow_final}') #pres_inflow=148142 #temp_inflow=297.169 #rho_inflow=2.63872 #mach_inflow=infloM = 0.139145 vel_inflow[0] = inlet_mach*math.sqrt(gamma_CO2*pres_inflow/rho_inflow) # starting pressure for the inflow ramp #timestepper = rk4_step #timestepper = lsrk54_step timestepper = lsrk144_step #timestepper = euler_step eos = IdealSingleGas(gamma=gamma_CO2, gas_const=R_CO2) bulk_init = Discontinuity(dim=dim, x0=-.30,sigma=0.005, #bulk_init = Discontinuity(dim=dim, x0=-.31,sigma=0.04, rhol=rho_inflow, rhor=rho_bkrnd, pl=pres_inflow, pr=pres_bkrnd, ul=vel_inflow, ur=vel_outflow) #inflow_init = Lump(dim=dim, rho0=rho_inflow, p0=pres_inflow, #center=orig, velocity=vel_inflow, rhoamp=0.0) #outflow_init = Lump(dim=dim, rho0=rho_bkrnd, p0=pres_bkrnd, #center=orig, velocity=vel_outflow, rhoamp=0.0) # pressure ramp function def inflow_ramp_pressure(t, startP=start_ramp_pres, finalP=end_ramp_pres, ramp_interval=ramp_interval, t_ramp_start=t_ramp_start): if t > t_ramp_start: rampPressure = min(finalP, startP+(t-t_ramp_start)/ramp_interval*(finalP-startP)) else: rampPressure = startP return rampPressure class IsentropicInflow: def __init__(self, *, dim=1, direc=0, T0=298, P0=1e5, mach= 0.01, p_fun = None): self._P0 = P0 self._T0 = T0 self._dim = dim self._direc = direc self._mach = mach if p_fun is not None: self._p_fun = p_fun def __call__(self, x_vec, *, t=0, eos): if self._p_fun is not None: P0 = self._p_fun(t) else: P0 = self._P0 T0 = self._T0 gamma = eos.gamma() gas_const = eos.gas_const() pressure = getIsentropicPressure(mach=self._mach, P0=P0, gamma=gamma) temperature = getIsentropicTemperature(mach=self._mach, T0=T0, gamma=gamma) rho = pressure/temperature/gas_const #print(f'ramp Mach number {self._mach}') #print(f'ramp stagnation pressure {P0}') #print(f'ramp stagnation temperature {T0}') #print(f'ramp pressure {pressure}') #print(f'ramp temperature {temperature}') velocity = np.zeros(shape=(self._dim,)) velocity[self._direc] = self._mach*math.sqrt(gamma*pressure/rho) mass = 0.0*x_vec[0] + rho mom = velocity*mass energy = (pressure/(gamma - 1.0)) + np.dot(mom, mom)/(2.0*mass) from mirgecom.euler import join_conserved return join_conserved(dim=self._dim, mass=mass, momentum=mom, energy=energy) inflow_init = IsentropicInflow(dim=dim, T0=298, P0=start_ramp_pres, mach = inlet_mach , p_fun=inflow_ramp_pressure) outflow_init = Uniform(dim=dim, rho=rho_bkrnd, p=pres_bkrnd, velocity=vel_outflow) inflow = PrescribedBoundary(inflow_init) outflow = PrescribedBoundary(outflow_init) wall = AdiabaticSlipBoundary() dummy = DummyBoundary() alpha_sc = 0.5 # s0 is ~p^-4 #s0_sc = -11.0 s0_sc = -5.0 # kappa is empirical ... kappa_sc = 0.5 print(f"Shock capturing parameters: alpha {alpha_sc}, s0 {s0_sc}, kappa {kappa_sc}") # timestep estimate #wave_speed = max(mach2*c_bkrnd,c_shkd+velocity2[0]) #char_len = 0.001 #area=char_len*char_len/2 #perimeter = 2*char_len+math.sqrt(2*char_len*char_len) #h = 2*area/perimeter #dt_est = 1/(wave_speed*order*order/h) #print(f"Time step estimate {dt_est}\n") # #dt_est_visc = 1/(wave_speed*order*order/h+alpha_sc*order*order*order*order/h/h) #print(f"Viscous timestep estimate {dt_est_visc}\n") from grudge import sym boundaries = {sym.DTAG_BOUNDARY("Inflow"): inflow, sym.DTAG_BOUNDARY("Outflow"): outflow, sym.DTAG_BOUNDARY("Wall"): wall} if restart_step is None: local_mesh, global_nelements = create_parallel_grid(comm, get_pseudo_y0_mesh) local_nelements = local_mesh.nelements else: # Restart with open(snapshot_pattern.format(step=restart_step, rank=rank), "rb") as f: restart_data = pickle.load(f) local_mesh = restart_data["local_mesh"] local_nelements = local_mesh.nelements global_nelements = restart_data["global_nelements"] assert comm.Get_size() == restart_data["num_parts"] if rank == 0: logging.info("Making discretization") discr = EagerDGDiscretization( actx, local_mesh, order=order, mpi_communicator=comm ) nodes = thaw(actx, discr.nodes()) if restart_step is None: if rank == 0: logging.info("Initializing soln.") # for Discontinuity initial conditions current_state = bulk_init(0, nodes, eos=eos) # for uniform background initial condition #current_state = bulk_init(nodes, eos=eos) else: current_t = restart_data["t"] current_step = restart_step current_state = unflatten( actx, discr.discr_from_dd("vol"), obj_array_vectorize(actx.from_numpy, restart_data["state"])) vis_timer = None if logmgr: logmgr_add_device_name(logmgr, queue) logmgr_add_many_discretization_quantities(logmgr, discr, dim, extract_vars_for_logging, units_for_logging) #logmgr_add_package_versions(logmgr) logmgr.add_watches(["step.max", "t_sim.max", "t_step.max", "t_log.max", "min_pressure", "max_pressure", "min_temperature", "max_temperature"]) try: logmgr.add_watches(["memory_usage.max"]) except KeyError: pass if use_profiling: logmgr.add_watches(["pyopencl_array_time.max"]) vis_timer = IntervalTimer("t_vis", "Time spent visualizing") logmgr.add_quantity(vis_timer) visualizer = make_visualizer(discr, discr.order + 3 if discr.dim == 2 else discr.order) # initname = initializer.__class__.__name__ initname = "pseudoY0" eosname = eos.__class__.__name__ init_message = make_init_message(dim=dim, order=order, nelements=local_nelements, global_nelements=global_nelements, dt=current_dt, t_final=t_final, nstatus=nstatus, nviz=nviz, cfl=current_cfl, constant_cfl=constant_cfl, initname=initname, eosname=eosname, casename=casename) if rank == 0: logger.info(init_message) get_timestep = partial(inviscid_sim_timestep, discr=discr, t=current_t, dt=current_dt, cfl=current_cfl, eos=eos, t_final=t_final, constant_cfl=constant_cfl) def my_rhs(t, state): #return inviscid_operator(discr, eos=eos, boundaries=boundaries, q=state, t=t) return ( inviscid_operator(discr, q=state, t=t,boundaries=boundaries, eos=eos) + artificial_viscosity(discr,t=t, r=state, eos=eos, boundaries=boundaries, alpha=alpha_sc, s0=s0_sc, kappa=kappa_sc)) def my_checkpoint(step, t, dt, state): write_restart = (check_step(step, nrestart) if step != restart_step else False) if write_restart is True: with open(snapshot_pattern.format(step=step, rank=rank), "wb") as f: pickle.dump({ "local_mesh": local_mesh, "state": obj_array_vectorize(actx.to_numpy, flatten(state)), "t": t, "step": step, "global_nelements": global_nelements, "num_parts": nparts, }, f) return sim_checkpoint(discr=discr, visualizer=visualizer, eos=eos, q=state, vizname=casename, step=step, t=t, dt=dt, nstatus=nstatus, nviz=nviz, exittol=exittol, constant_cfl=constant_cfl, comm=comm, vis_timer=vis_timer, overwrite=True,s0=s0_sc,kappa=kappa_sc) if rank == 0: logging.info("Stepping.") (current_step, current_t, current_state) = \ advance_state(rhs=my_rhs, timestepper=timestepper, checkpoint=my_checkpoint, get_timestep=get_timestep, state=current_state, t_final=t_final, t=current_t, istep=current_step, logmgr=logmgr,eos=eos,dim=dim) if rank == 0: logger.info("Checkpointing final state ...") my_checkpoint(current_step, t=current_t, dt=(current_t - checkpoint_t), state=current_state) if current_t - t_final < 0: raise ValueError("Simulation exited abnormally") if logmgr: logmgr.close() elif use_profiling: print(actx.tabulate_profiling_data())
def test_multilump_rhs(actx_factory, dim, order, v0): """Tests the inviscid rhs using the non-trivial 1, 2, and 3D mass lump case against the analytic expressions of the RHS. Checks several different orders and refinement levels to check error behavior. """ actx = actx_factory() nspecies = 10 tolerance = 1e-8 maxxerr = 0.0 from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() for nel_1d in [4, 8, 16]: from meshmode.mesh.generation import ( generate_regular_rect_mesh, ) mesh = generate_regular_rect_mesh( a=(-1, ) * dim, b=(1, ) * dim, nelements_per_axis=(nel_1d, ) * dim, ) logger.info(f"Number of elements: {mesh.nelements}") discr = EagerDGDiscretization(actx, mesh, order=order) nodes = thaw(actx, discr.nodes()) centers = make_obj_array( [np.zeros(shape=(dim, )) for i in range(nspecies)]) spec_y0s = np.ones(shape=(nspecies, )) spec_amplitudes = np.ones(shape=(nspecies, )) velocity = np.zeros(shape=(dim, )) velocity[0] = v0 rho0 = 2.0 lump = MulticomponentLump(dim=dim, nspecies=nspecies, rho0=rho0, spec_centers=centers, velocity=velocity, spec_y0s=spec_y0s, spec_amplitudes=spec_amplitudes) lump_soln = lump(nodes) boundaries = {BTAG_ALL: PrescribedBoundary(lump)} inviscid_rhs = euler_operator(discr, eos=IdealSingleGas(), boundaries=boundaries, cv=lump_soln, t=0.0) expected_rhs = lump.exact_rhs(discr, cv=lump_soln, t=0) print(f"inviscid_rhs = {inviscid_rhs}") print(f"expected_rhs = {expected_rhs}") err_max = discr.norm((inviscid_rhs - expected_rhs).join(), np.inf) if err_max > maxxerr: maxxerr = err_max eoc_rec.add_data_point(1.0 / nel_1d, err_max) logger.info(f"Max error: {maxxerr}") logger.info(f"Error for (dim,order) = ({dim},{order}):\n" f"{eoc_rec}") assert (eoc_rec.order_estimate() >= order - 0.5 or eoc_rec.max_error() < tolerance)
def main(ctx_factory=cl.create_some_context, use_leap=False): """Drive the example.""" cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue, allocator=cl_tools.MemoryPool( cl_tools.ImmediateAllocator(queue))) logger = logging.getLogger(__name__) dim = 2 nel_1d = 16 order = 1 exittol = 2e-2 exittol = 100.0 t_final = 0.1 current_cfl = 1.0 vel = np.zeros(shape=(dim, )) orig = np.zeros(shape=(dim, )) # vel[:dim] = 1.0 current_dt = .01 current_t = 0 eos = IdealSingleGas() initializer = Lump(dim=dim, center=orig, velocity=vel, rhoamp=0.0) casename = "pulse" boundaries = {BTAG_ALL: PrescribedBoundary(initializer)} wall = AdiabaticSlipBoundary() boundaries = {BTAG_ALL: wall} constant_cfl = False nstatus = 10 nviz = 10 rank = 0 checkpoint_t = current_t current_step = 0 if use_leap: from leap.rk import RK4MethodBuilder timestepper = RK4MethodBuilder("state") else: timestepper = rk4_step box_ll = -0.5 box_ur = 0.5 from mpi4py import MPI comm = MPI.COMM_WORLD nproc = comm.Get_size() rank = comm.Get_rank() num_parts = nproc from meshmode.mesh.generation import generate_regular_rect_mesh if num_parts > 1: generate_mesh = partial(generate_regular_rect_mesh, a=(box_ll, ) * dim, b=(box_ur, ) * dim, nelements_per_axis=(nel_1d, ) * dim) local_mesh, global_nelements = generate_and_distribute_mesh( comm, generate_mesh) else: local_mesh = generate_regular_rect_mesh(a=(box_ll, ) * dim, b=(box_ur, ) * dim, nelements_per_axis=(nel_1d, ) * dim) global_nelements = local_mesh.nelements local_nelements = local_mesh.nelements discr = EagerDGDiscretization(actx, local_mesh, order=order, mpi_communicator=comm) nodes = thaw(actx, discr.nodes()) uniform_state = initializer(nodes) acoustic_pulse = AcousticPulse(dim=dim, amplitude=1.0, width=.1, center=orig) current_state = acoustic_pulse(x_vec=nodes, cv=uniform_state, eos=eos) visualizer = make_visualizer(discr) initname = "pulse" eosname = eos.__class__.__name__ init_message = make_init_message(dim=dim, order=order, nelements=local_nelements, global_nelements=global_nelements, dt=current_dt, t_final=t_final, nstatus=nstatus, nviz=nviz, cfl=current_cfl, constant_cfl=constant_cfl, initname=initname, eosname=eosname, casename=casename) if rank == 0: logger.info(init_message) get_timestep = partial(inviscid_sim_timestep, discr=discr, t=current_t, dt=current_dt, cfl=current_cfl, eos=eos, t_final=t_final, constant_cfl=constant_cfl) def my_rhs(t, state): return euler_operator(discr, cv=state, t=t, boundaries=boundaries, eos=eos) def my_checkpoint(step, t, dt, state): return sim_checkpoint(discr, visualizer, eos, cv=state, vizname=casename, step=step, t=t, dt=dt, nstatus=nstatus, nviz=nviz, exittol=exittol, constant_cfl=constant_cfl, comm=comm) try: (current_step, current_t, current_state) = \ advance_state(rhs=my_rhs, timestepper=timestepper, checkpoint=my_checkpoint, get_timestep=get_timestep, state=current_state, t=current_t, t_final=t_final) except ExactSolutionMismatch as ex: current_step = ex.step current_t = ex.t current_state = ex.state # if current_t != checkpoint_t: if rank == 0: logger.info("Checkpointing final state ...") my_checkpoint(current_step, t=current_t, dt=(current_t - checkpoint_t), state=current_state) if current_t - t_final < 0: raise ValueError("Simulation exited abnormally")