def my_write_status(state, component_errors, cfl=None): if cfl is None: if constant_cfl: cfl = current_cfl else: from grudge.op import nodal_max from mirgecom.inviscid import get_inviscid_cfl cfl = actx.to_numpy( nodal_max(discr, "vol", get_inviscid_cfl(discr, state, current_dt)))[()] if rank == 0: logger.info(f"------ {cfl=}\n" "------- errors=" + ", ".join("%.3g" % en for en in component_errors))
def my_get_timestep(t, dt, state): # richer interface to calculate {dt,cfl} returns node-local estimates t_remaining = max(0, t_final - t) if constant_cfl: from mirgecom.inviscid import get_inviscid_timestep ts_field = current_cfl * get_inviscid_timestep( discr, eos=eos, cv=state) from grudge.op import nodal_min dt = nodal_min(discr, "vol", ts_field) cfl = current_cfl else: from mirgecom.inviscid import get_inviscid_cfl ts_field = get_inviscid_cfl(discr, eos=eos, dt=dt, cv=state) from grudge.op import nodal_max cfl = nodal_max(discr, "vol", ts_field) return ts_field, cfl, min(t_remaining, dt)
def my_checkpoint(step, t, dt, state, force=False): do_health = force or check_step(step, nhealth) and step > 0 do_viz = force or check_step(step, nviz) do_restart = force or check_step(step, nrestart) do_status = force or check_step(step, nstatus) if do_viz or do_health: dv = eos.dependent_vars(state) errors = False if do_health: health_message = "" if check_naninf_local(discr, "vol", dv.pressure): errors = True health_message += "Invalid pressure data found.\n" elif check_range_local(discr, "vol", dv.pressure, min_value=1, max_value=2.e6): errors = True health_message += "Pressure data failed health check.\n" errors = comm.allreduce(errors, MPI.LOR) if errors: if rank == 0: logger.info("Fluid solution failed health check.") if health_message: logger.info(f"{rank=}: {health_message}") #if check_step(step, nrestart) and step != restart_step and not errors: if do_restart or errors: filename = restart_path + snapshot_pattern.format( step=step, rank=rank, casename=casename) restart_dictionary = { "local_mesh": local_mesh, "order": order, "state": state, "t": t, "step": step, "global_nelements": global_nelements, "num_parts": nparts } write_restart_file(actx, restart_dictionary, filename, comm) if do_status or do_viz or errors: local_cfl = get_inviscid_cfl(discr, eos=eos, dt=dt, cv=state) max_cfl = nodal_max(discr, "vol", local_cfl) log_cfl.set_quantity(max_cfl) #if ((check_step(step, nviz) and step != restart_step) or errors): if do_viz or errors: def loc_fn(t): return flame_start_loc + flame_speed * t #exact_soln = PlanarDiscontinuity(dim=dim, disc_location=loc_fn, #sigma=0.0000001, nspecies=nspecies, #temperature_left=temp_ignition, temperature_right=temp_unburned, #pressure_left=pres_burned, pressure_right=pres_unburned, #velocity_left=vel_burned, velocity_right=vel_unburned, #species_mass_left=y_burned, species_mass_right=y_unburned) reaction_rates = eos.get_production_rates(cv=state) # conserved quantities viz_fields = [ #("cv", state), ("CV_rho", state.mass), ("CV_rhoU", state.momentum[0]), ("CV_rhoV", state.momentum[1]), ("CV_rhoE", state.energy) ] # species mass fractions viz_fields.extend( ("Y_" + species_names[i], state.species_mass[i] / state.mass) for i in range(nspecies)) # dependent variables viz_fields.extend([ ("DV", eos.dependent_vars(state)), #("exact_soln", exact_soln), ("reaction_rates", reaction_rates), ("cfl", local_cfl) ]) write_visfile(discr, viz_fields, visualizer, vizname=viz_path + casename, step=step, t=t, overwrite=True, vis_timer=vis_timer) if errors: raise RuntimeError("Error detected by user checkpoint, exiting.")
def max_characteristic_velocity(self, actx, **kwargs): if self.fixed_material: return 1 / np.sqrt(self.epsilon * self.mu) # a number else: return op.nodal_max(self.dcoll, "vol", 1 / actx.np.sqrt(self.epsilon * self.mu))
def main(ctx_factory, dim=2, order=3, visualize=False, lazy=False): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) if lazy: actx = PytatoPyOpenCLArrayContext(queue) else: actx = PyOpenCLArrayContext( queue, allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)), force_device_scalars=True, ) comm = MPI.COMM_WORLD num_parts = comm.Get_size() from meshmode.distributed import MPIMeshDistributor, get_partition_by_pymetis mesh_dist = MPIMeshDistributor(comm) nel_1d = 16 if mesh_dist.is_mananger_rank(): from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim, b=(0.5, ) * dim, nelements_per_axis=(nel_1d, ) * dim) logger.info("%d elements", mesh.nelements) part_per_element = get_partition_by_pymetis(mesh, num_parts) local_mesh = mesh_dist.send_mesh_parts(mesh, part_per_element, num_parts) del mesh else: local_mesh = mesh_dist.receive_mesh_part() dcoll = DiscretizationCollection(actx, local_mesh, order=order, mpi_communicator=comm) fields = WaveState(u=bump(actx, dcoll), v=make_obj_array( [dcoll.zeros(actx) for i in range(dcoll.dim)])) c = 1 dt = actx.to_numpy(0.45 * estimate_rk4_timestep(actx, dcoll, c)) vis = make_visualizer(dcoll) def rhs(t, w): return wave_operator(dcoll, c=c, w=w) compiled_rhs = actx.compile(rhs) if comm.rank == 0: logger.info("dt = %g", dt) import time start = time.time() t = 0 t_final = 3 istep = 0 while t < t_final: if lazy: fields = thaw(freeze(fields, actx), actx) fields = rk4_step(fields, t, dt, compiled_rhs) l2norm = actx.to_numpy(op.norm(dcoll, fields.u, 2)) if istep % 10 == 0: stop = time.time() linfnorm = actx.to_numpy(op.norm(dcoll, fields.u, np.inf)) nodalmax = actx.to_numpy(op.nodal_max(dcoll, "vol", fields.u)) nodalmin = actx.to_numpy(op.nodal_min(dcoll, "vol", fields.u)) if comm.rank == 0: logger.info(f"step: {istep} t: {t} " f"L2: {l2norm} " f"Linf: {linfnorm} " f"sol max: {nodalmax} " f"sol min: {nodalmin} " f"wall: {stop-start} ") if visualize: vis.write_parallel_vtk_file( comm, f"fld-wave-eager-mpi-{{rank:03d}}-{istep:04d}.vtu", [ ("u", fields.u), ("v", fields.v), ]) start = stop t += dt istep += 1 # NOTE: These are here to ensure the solution is bounded for the # time interval specified assert l2norm < 1
def nodal_max(self, dd, vec): return op.nodal_max(self, dd, vec)