def mpi_communication_entrypoint(): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from mpi4py import MPI comm = MPI.COMM_WORLD i_local_rank = comm.Get_rank() num_parts = comm.Get_size() from meshmode.distributed import MPIMeshDistributor, get_partition_by_pymetis mesh_dist = MPIMeshDistributor(comm) dim = 2 dt = 0.04 order = 4 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, n=(16, ) * dim) part_per_element = get_partition_by_pymetis(mesh, num_parts) local_mesh = mesh_dist.send_mesh_parts(mesh, part_per_element, num_parts) else: local_mesh = mesh_dist.receive_mesh_part() vol_discr = DGDiscretizationWithBoundaries(cl_ctx, local_mesh, order=order, mpi_communicator=comm) source_center = np.array([0.1, 0.22, 0.33])[:local_mesh.dim] source_width = 0.05 source_omega = 3 sym_x = sym.nodes(local_mesh.dim) sym_source_center_dist = sym_x - source_center sym_t = sym.ScalarVariable("t") from grudge.models.wave import StrongWaveOperator from meshmode.mesh import BTAG_ALL, BTAG_NONE op = StrongWaveOperator( -0.1, vol_discr.dim, source_f=( sym.sin(source_omega * sym_t) * sym.exp(-np.dot(sym_source_center_dist, sym_source_center_dist) / source_width**2)), dirichlet_tag=BTAG_NONE, neumann_tag=BTAG_NONE, radiation_tag=BTAG_ALL, flux_type="upwind") from pytools.obj_array import join_fields fields = join_fields( vol_discr.zeros(queue), [vol_discr.zeros(queue) for i in range(vol_discr.dim)]) # FIXME # dt = op.estimate_rk4_timestep(vol_discr, fields=fields) # FIXME: Should meshmode consider BTAG_PARTITION to be a boundary? # Fails because: "found faces without boundary conditions" # op.check_bc_coverage(local_mesh) from pytools.log import LogManager, \ add_general_quantities, \ add_run_info, \ IntervalTimer, EventCounter log_filename = None # NOTE: LogManager hangs when using a file on a shared directory. # log_filename = 'grudge_log.dat' logmgr = LogManager(log_filename, "w", comm) add_run_info(logmgr) add_general_quantities(logmgr) log_quantities =\ {"rank_data_swap_timer": IntervalTimer("rank_data_swap_timer", "Time spent evaluating RankDataSwapAssign"), "rank_data_swap_counter": EventCounter("rank_data_swap_counter", "Number of RankDataSwapAssign instructions evaluated"), "exec_timer": IntervalTimer("exec_timer", "Total time spent executing instructions"), "insn_eval_timer": IntervalTimer("insn_eval_timer", "Time spend evaluating instructions"), "future_eval_timer": IntervalTimer("future_eval_timer", "Time spent evaluating futures"), "busy_wait_timer": IntervalTimer("busy_wait_timer", "Time wasted doing busy wait")} for quantity in log_quantities.values(): logmgr.add_quantity(quantity) # print(sym.pretty(op.sym_operator())) bound_op = bind(vol_discr, op.sym_operator()) # print(bound_op) # 1/0 def rhs(t, w): val, rhs.profile_data = bound_op(queue, profile_data=rhs.profile_data, log_quantities=log_quantities, t=t, w=w) return val rhs.profile_data = {} dt_stepper = set_up_rk4("w", dt, fields, rhs) final_t = 4 nsteps = int(final_t / dt) print("rank=%d dt=%g nsteps=%d" % (i_local_rank, dt, nsteps)) # from grudge.shortcuts import make_visualizer # vis = make_visualizer(vol_discr, vis_order=order) step = 0 norm = bind(vol_discr, sym.norm(2, sym.var("u"))) from time import time t_last_step = time() logmgr.tick_before() for event in dt_stepper.run(t_end=final_t): if isinstance(event, dt_stepper.StateComputed): assert event.component_id == "w" step += 1 print(step, event.t, norm(queue, u=event.state_component[0]), time() - t_last_step) # if step % 10 == 0: # vis.write_vtk_file("rank%d-fld-%04d.vtu" % (i_local_rank, step), # [("u", event.state_component[0]), # ("v", event.state_component[1:])]) t_last_step = time() logmgr.tick_after() logmgr.tick_before() logmgr.tick_after() def print_profile_data(data): print("""execute() for rank %d: \tInstruction Evaluation: %f%% \tFuture Evaluation: %f%% \tBusy Wait: %f%% \tTotal: %f seconds""" % (i_local_rank, data['insn_eval_time'] / data['total_time'] * 100, data['future_eval_time'] / data['total_time'] * 100, data['busy_wait_time'] / data['total_time'] * 100, data['total_time'])) print_profile_data(rhs.profile_data) logmgr.close() logger.debug("Rank %d exiting", i_local_rank)
def simple_wave_entrypoint(dim=2, num_elems=256, order=4, num_steps=30, log_filename="grudge.dat"): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) from mpi4py import MPI comm = MPI.COMM_WORLD num_parts = comm.Get_size() n = int(num_elems ** (1./dim)) from meshmode.distributed import MPIMeshDistributor mesh_dist = MPIMeshDistributor(comm) 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, n=(n,)*dim) from pymetis import part_graph _, p = part_graph(num_parts, xadj=mesh.nodal_adjacency.neighbors_starts.tolist(), adjncy=mesh.nodal_adjacency.neighbors.tolist()) part_per_element = np.array(p) local_mesh = mesh_dist.send_mesh_parts(mesh, part_per_element, num_parts) else: local_mesh = mesh_dist.receive_mesh_part() vol_discr = DGDiscretizationWithBoundaries(cl_ctx, local_mesh, order=order, mpi_communicator=comm) source_center = np.array([0.1, 0.22, 0.33])[:local_mesh.dim] source_width = 0.05 source_omega = 3 sym_x = sym.nodes(local_mesh.dim) sym_source_center_dist = sym_x - source_center sym_t = sym.ScalarVariable("t") from grudge.models.wave import StrongWaveOperator from meshmode.mesh import BTAG_ALL, BTAG_NONE op = StrongWaveOperator(-0.1, vol_discr.dim, source_f=( sym.sin(source_omega*sym_t) * sym.exp( -np.dot(sym_source_center_dist, sym_source_center_dist) / source_width**2)), dirichlet_tag=BTAG_NONE, neumann_tag=BTAG_NONE, radiation_tag=BTAG_ALL, flux_type="upwind") from pytools.obj_array import join_fields fields = join_fields(vol_discr.zeros(queue), [vol_discr.zeros(queue) for i in range(vol_discr.dim)]) from logpyle import LogManager, \ add_general_quantities, \ add_run_info, \ IntervalTimer, EventCounter # NOTE: LogManager hangs when using a file on a shared directory. logmgr = LogManager(log_filename, "w", comm) add_run_info(logmgr) add_general_quantities(logmgr) log_quantities =\ {"rank_data_swap_timer": IntervalTimer("rank_data_swap_timer", "Time spent evaluating RankDataSwapAssign"), "rank_data_swap_counter": EventCounter("rank_data_swap_counter", "Number of RankDataSwapAssign instructions evaluated"), "exec_timer": IntervalTimer("exec_timer", "Total time spent executing instructions"), "insn_eval_timer": IntervalTimer("insn_eval_timer", "Time spend evaluating instructions"), "future_eval_timer": IntervalTimer("future_eval_timer", "Time spent evaluating futures"), "busy_wait_timer": IntervalTimer("busy_wait_timer", "Time wasted doing busy wait")} for quantity in log_quantities.values(): logmgr.add_quantity(quantity) bound_op = bind(vol_discr, op.sym_operator()) def rhs(t, w): val, rhs.profile_data = bound_op(queue, profile_data=rhs.profile_data, log_quantities=log_quantities, t=t, w=w) return val rhs.profile_data = {} dt = 0.04 dt_stepper = set_up_rk4("w", dt, fields, rhs) logmgr.tick_before() for event in dt_stepper.run(t_end=dt * num_steps): if isinstance(event, dt_stepper.StateComputed): logmgr.tick_after() logmgr.tick_before() logmgr.tick_after() def print_profile_data(data): print("""execute() for rank %d: \tInstruction Evaluation: %f%% \tFuture Evaluation: %f%% \tBusy Wait: %f%% \tTotal: %f seconds""" % (comm.Get_rank(), data['insn_eval_time'] / data['total_time'] * 100, data['future_eval_time'] / data['total_time'] * 100, data['busy_wait_time'] / data['total_time'] * 100, data['total_time'])) print_profile_data(rhs.profile_data) logmgr.close()
def main(ctx_factory, dim=3, order=4, visualize=False): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext( queue, allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)), force_device_scalars=True, ) from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(0.0, ) * dim, b=(1.0, ) * dim, nelements_per_axis=(4, ) * dim) dcoll = DiscretizationCollection(actx, mesh, order=order) if 0: epsilon0 = 8.8541878176e-12 # C**2 / (N m**2) mu0 = 4 * np.pi * 1e-7 # N/A**2. epsilon = 1 * epsilon0 mu = 1 * mu0 else: epsilon = 1 mu = 1 from grudge.models.em import MaxwellOperator maxwell_operator = MaxwellOperator(dcoll, epsilon, mu, flux_type=0.5, dimensions=dim) def cavity_mode(x, t=0): if dim == 3: return get_rectangular_cavity_mode(actx, x, t, 1, (1, 2, 2)) else: return get_rectangular_cavity_mode(actx, x, t, 1, (2, 3)) fields = cavity_mode(thaw(dcoll.nodes(), actx), t=0) maxwell_operator.check_bc_coverage(mesh) def rhs(t, w): return maxwell_operator.operator(t, w) dt = maxwell_operator.estimate_rk4_timestep(actx, dcoll, fields=fields) dt_stepper = set_up_rk4("w", dt, fields, rhs) target_steps = 60 final_t = dt * target_steps nsteps = int(final_t / dt) + 1 logger.info("dt = %g nsteps = %d", dt, nsteps) from grudge.shortcuts import make_visualizer vis = make_visualizer(dcoll) step = 0 def norm(u): return op.norm(dcoll, u, 2) e, h = maxwell_operator.split_eh(fields) if visualize: vis.write_vtk_file(f"fld-cavities-{step:04d}.vtu", [ ("e", e), ("h", h), ]) for event in dt_stepper.run(t_end=final_t): if isinstance(event, dt_stepper.StateComputed): assert event.component_id == "w" step += 1 e, h = maxwell_operator.split_eh(event.state_component) norm_e0 = actx.to_numpy(norm(u=e[0])) norm_e1 = actx.to_numpy(norm(u=e[1])) norm_h0 = actx.to_numpy(norm(u=h[0])) norm_h1 = actx.to_numpy(norm(u=h[1])) logger.info( "[%04d] t = %.5f |e0| = %.5e, |e1| = %.5e, |h0| = %.5e, |h1| = %.5e", step, event.t, norm_e0, norm_e1, norm_h0, norm_h1) if step % 10 == 0: if visualize: vis.write_vtk_file(f"fld-cavities-{step:04d}.vtu", [ ("e", e), ("h", h), ]) # NOTE: These are here to ensure the solution is bounded for the # time interval specified assert norm_e0 < 0.5 assert norm_e1 < 0.5 assert norm_h0 < 0.5 assert norm_h1 < 0.5
def main(ctx_factory, dim=2, order=4, visualize=False): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext( queue, allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)), force_device_scalars=True, ) # {{{ parameters # domain [-d/2, d/2]^dim d = 1.0 # number of points in each dimension npoints = 20 # final time final_time = 1.0 # velocity field c = np.array([0.5] * dim) norm_c = la.norm(c) # flux flux_type = "central" # }}} # {{{ discretization from meshmode.mesh.generation import generate_box_mesh mesh = generate_box_mesh( [np.linspace(-d / 2, d / 2, npoints) for _ in range(dim)], order=order) from grudge import DiscretizationCollection dcoll = DiscretizationCollection(actx, mesh, order=order) # }}} # {{{ weak advection operator def f(x): return actx.np.sin(3 * x) def u_analytic(x, t=0): return f(-np.dot(c, x) / norm_c + t * norm_c) from grudge.models.advection import WeakAdvectionOperator adv_operator = WeakAdvectionOperator( dcoll, c, inflow_u=lambda t: u_analytic(thaw(dcoll.nodes(dd=BTAG_ALL), actx), t=t), flux_type=flux_type) nodes = thaw(dcoll.nodes(), actx) u = u_analytic(nodes, t=0) def rhs(t, u): return adv_operator.operator(t, u) dt = actx.to_numpy( adv_operator.estimate_rk4_timestep(actx, dcoll, fields=u)) logger.info("Timestep size: %g", dt) # }}} # {{{ time stepping from grudge.shortcuts import set_up_rk4 dt_stepper = set_up_rk4("u", dt, u, rhs) plot = Plotter(actx, dcoll, order, visualize=visualize, ylim=[-1.1, 1.1]) step = 0 norm_u = 0.0 for event in dt_stepper.run(t_end=final_time): if not isinstance(event, dt_stepper.StateComputed): continue if step % 10 == 0: norm_u = actx.to_numpy(op.norm(dcoll, event.state_component, 2)) plot(event, "fld-weak-%04d" % step) step += 1 logger.info("[%04d] t = %.5f |u| = %.5e", step, event.t, norm_u) # NOTE: These are here to ensure the solution is bounded for the # time interval specified assert norm_u < 1
def mpi_communication_entrypoint(): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue, force_device_scalars=True) from mpi4py import MPI comm = MPI.COMM_WORLD i_local_rank = comm.Get_rank() num_parts = comm.Get_size() from meshmode.distributed import MPIMeshDistributor, get_partition_by_pymetis mesh_dist = MPIMeshDistributor(comm) dim = 2 order = 4 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=(16,)*dim) 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) def source_f(actx, dcoll, t=0): source_center = np.array([0.1, 0.22, 0.33])[:dcoll.dim] source_width = 0.05 source_omega = 3 nodes = thaw(dcoll.nodes(), actx) source_center_dist = flat_obj_array( [nodes[i] - source_center[i] for i in range(dcoll.dim)] ) return ( np.sin(source_omega*t) * actx.np.exp( -np.dot(source_center_dist, source_center_dist) / source_width**2 ) ) from grudge.models.wave import WeakWaveOperator from meshmode.mesh import BTAG_ALL, BTAG_NONE wave_op = WeakWaveOperator( dcoll, 0.1, source_f=source_f, dirichlet_tag=BTAG_NONE, neumann_tag=BTAG_NONE, radiation_tag=BTAG_ALL, flux_type="upwind" ) fields = flat_obj_array( dcoll.zeros(actx), [dcoll.zeros(actx) for i in range(dcoll.dim)] ) dt = actx.to_numpy( 2/3 * wave_op.estimate_rk4_timestep(actx, dcoll, fields=fields)) wave_op.check_bc_coverage(local_mesh) from logpyle import LogManager, \ add_general_quantities, \ add_run_info log_filename = None # NOTE: LogManager hangs when using a file on a shared directory. # log_filename = "grudge_log.dat" logmgr = LogManager(log_filename, "w", comm) add_run_info(logmgr) add_general_quantities(logmgr) def rhs(t, w): return wave_op.operator(t, w) dt_stepper = set_up_rk4("w", dt, fields, rhs) final_t = 4 nsteps = int(final_t/dt) logger.info("[%04d] dt %.5e nsteps %4d", i_local_rank, dt, nsteps) step = 0 def norm(u): return op.norm(dcoll, u, 2) from time import time t_last_step = time() logmgr.tick_before() for event in dt_stepper.run(t_end=final_t): if isinstance(event, dt_stepper.StateComputed): assert event.component_id == "w" step += 1 logger.info("[%04d] t = %.5e |u| = %.5e ellapsed %.5e", step, event.t, norm(u=event.state_component[0]), time() - t_last_step) t_last_step = time() logmgr.tick_after() logmgr.tick_before() logmgr.tick_after() logmgr.close() logger.info("Rank %d exiting", i_local_rank)
def test_convergence_maxwell(ctx_factory, order): """Test whether 3D Maxwell's actually converges""" cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() dims = 3 ns = [4, 6, 8] for n in ns: from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(0.0, ) * dims, b=(1.0, ) * dims, n=(n, ) * dims) discr = DGDiscretizationWithBoundaries(actx, mesh, order=order) epsilon = 1 mu = 1 from grudge.models.em import get_rectangular_cavity_mode sym_mode = get_rectangular_cavity_mode(1, (1, 2, 2)) analytic_sol = bind(discr, sym_mode) fields = analytic_sol(actx, t=0, epsilon=epsilon, mu=mu) from grudge.models.em import MaxwellOperator op = MaxwellOperator(epsilon, mu, flux_type=0.5, dimensions=dims) op.check_bc_coverage(mesh) bound_op = bind(discr, op.sym_operator()) def rhs(t, w): return bound_op(t=t, w=w) dt = 0.002 final_t = dt * 5 nsteps = int(final_t / dt) from grudge.shortcuts import set_up_rk4 dt_stepper = set_up_rk4("w", dt, fields, rhs) logger.info("dt %.5e nsteps %5d", dt, nsteps) norm = bind(discr, sym.norm(2, sym.var("u"))) step = 0 for event in dt_stepper.run(t_end=final_t): if isinstance(event, dt_stepper.StateComputed): assert event.component_id == "w" esc = event.state_component step += 1 logger.debug("[%04d] t = %.5e", step, event.t) sol = analytic_sol(actx, mu=mu, epsilon=epsilon, t=step * dt) vals = [norm(u=(esc[i] - sol[i])) / norm(u=sol[i]) for i in range(5)] # noqa E501 total_error = sum(vals) eoc_rec.add_data_point(1.0 / n, total_error) logger.info( "\n%s", eoc_rec.pretty_print(abscissa_label="h", error_label="L2 Error")) assert eoc_rec.order_estimate() > order
def main(dims, write_output=True, order=4): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(0.0, ) * dims, b=(1.0, ) * dims, nelements_per_axis=(4, ) * dims) discr = DiscretizationCollection(actx, mesh, order=order) if 0: epsilon0 = 8.8541878176e-12 # C**2 / (N m**2) mu0 = 4 * np.pi * 1e-7 # N/A**2. epsilon = 1 * epsilon0 mu = 1 * mu0 else: epsilon = 1 mu = 1 from grudge.models.em import MaxwellOperator op = MaxwellOperator(epsilon, mu, flux_type=0.5, dimensions=dims) if dims == 3: sym_mode = get_rectangular_cavity_mode(1, (1, 2, 2)) fields = bind(discr, sym_mode)(actx, t=0, epsilon=epsilon, mu=mu) else: sym_mode = get_rectangular_cavity_mode(1, (2, 3)) fields = bind(discr, sym_mode)(actx, t=0) # FIXME #dt = op.estimate_rk4_timestep(discr, fields=fields) op.check_bc_coverage(mesh) # print(sym.pretty(op.sym_operator())) bound_op = bind(discr, op.sym_operator()) def rhs(t, w): return bound_op(t=t, w=w) if mesh.dim == 2: dt = 0.004 elif mesh.dim == 3: dt = 0.002 dt_stepper = set_up_rk4("w", dt, fields, rhs) final_t = dt * STEPS nsteps = int(final_t / dt) print("dt=%g nsteps=%d" % (dt, nsteps)) from grudge.shortcuts import make_visualizer vis = make_visualizer(discr) step = 0 norm = bind(discr, sym.norm(2, sym.var("u"))) from time import time t_last_step = time() e, h = op.split_eh(fields) if 1: vis.write_vtk_file("fld-cavities-%04d.vtu" % step, [ ("e", e), ("h", h), ]) for event in dt_stepper.run(t_end=final_t): if isinstance(event, dt_stepper.StateComputed): assert event.component_id == "w" step += 1 print(step, event.t, norm(u=e[0]), norm(u=e[1]), norm(u=h[0]), norm(u=h[1]), time() - t_last_step) if step % 10 == 0: e, h = op.split_eh(event.state_component) vis.write_vtk_file("fld-cavities-%04d.vtu" % step, [ ("e", e), ("h", h), ]) t_last_step = time()
def main(write_output=True, order=4): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) dims = 2 from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh( a=(-0.5,)*dims, b=(0.5,)*dims, nelements_per_axis=(20,)*dims) discr = DiscretizationCollection(actx, mesh, order=order) source_center = np.array([0.1, 0.22, 0.33])[:mesh.dim] source_width = 0.05 source_omega = 3 sym_x = sym.nodes(mesh.dim) sym_source_center_dist = sym_x - source_center sym_t = sym.ScalarVariable("t") c = sym.If(sym.Comparison( np.dot(sym_x, sym_x), "<", 0.15), np.float32(0.1), np.float32(0.2)) from grudge.models.wave import VariableCoefficientWeakWaveOperator from meshmode.mesh import BTAG_ALL, BTAG_NONE op = VariableCoefficientWeakWaveOperator(c, discr.dim, source_f=( sym.sin(source_omega*sym_t) * sym.exp( -np.dot(sym_source_center_dist, sym_source_center_dist) / source_width**2)), dirichlet_tag=BTAG_NONE, neumann_tag=BTAG_NONE, radiation_tag=BTAG_ALL, flux_type="upwind") from pytools.obj_array import flat_obj_array fields = flat_obj_array(discr.zeros(actx), [discr.zeros(actx) for i in range(discr.dim)]) op.check_bc_coverage(mesh) c_eval = bind(discr, c)(actx) bound_op = bind(discr, op.sym_operator()) def rhs(t, w): return bound_op(t=t, w=w) if mesh.dim == 2: dt = 0.04 * 0.3 elif mesh.dim == 3: dt = 0.02 * 0.1 dt_stepper = set_up_rk4("w", dt, fields, rhs) final_t = 1 nsteps = int(final_t/dt) print("dt=%g nsteps=%d" % (dt, nsteps)) from grudge.shortcuts import make_visualizer vis = make_visualizer(discr) step = 0 norm = bind(discr, sym.norm(2, sym.var("u"))) from time import time t_last_step = time() for event in dt_stepper.run(t_end=final_t): if isinstance(event, dt_stepper.StateComputed): assert event.component_id == "w" step += 1 print(step, event.t, norm(u=event.state_component[0]), time()-t_last_step) if step % 10 == 0: vis.write_vtk_file("fld-var-propogation-speed-%04d.vtu" % step, [ ("u", event.state_component[0]), ("v", event.state_component[1:]), ("c", c_eval), ]) t_last_step = time()
def main(ctx_factory, dim=2, order=4, visualize=False): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) 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) 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=(16, ) * 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) def source_f(actx, dcoll, t=0): source_center = np.array([0.1, 0.22, 0.33])[:dcoll.dim] source_width = 0.05 source_omega = 3 nodes = thaw(dcoll.nodes(), actx) source_center_dist = flat_obj_array( [nodes[i] - source_center[i] for i in range(dcoll.dim)]) return (np.sin(source_omega * t) * actx.np.exp( -np.dot(source_center_dist, source_center_dist) / source_width**2)) from grudge.models.wave import WeakWaveOperator from meshmode.mesh import BTAG_ALL, BTAG_NONE wave_op = WeakWaveOperator(dcoll, 0.1, source_f=source_f, dirichlet_tag=BTAG_NONE, neumann_tag=BTAG_NONE, radiation_tag=BTAG_ALL, flux_type="upwind") fields = flat_obj_array(dcoll.zeros(actx), [dcoll.zeros(actx) for i in range(dcoll.dim)]) dt = 2 / 3 * wave_op.estimate_rk4_timestep(actx, dcoll, fields=fields) wave_op.check_bc_coverage(local_mesh) def rhs(t, w): return wave_op.operator(t, w) dt_stepper = set_up_rk4("w", dt, fields, rhs) final_t = 10 nsteps = int(final_t / dt) + 1 if comm.rank == 0: logger.info("dt=%g nsteps=%d", dt, nsteps) from grudge.shortcuts import make_visualizer vis = make_visualizer(dcoll) step = 0 def norm(u): return op.norm(dcoll, u, 2) from time import time t_last_step = time() if visualize: u = fields[0] v = fields[1:] vis.write_parallel_vtk_file( comm, f"fld-wave-min-mpi-{{rank:03d}}-{step:04d}.vtu", [ ("u", u), ("v", v), ]) for event in dt_stepper.run(t_end=final_t): if isinstance(event, dt_stepper.StateComputed): assert event.component_id == "w" step += 1 l2norm = norm(u=event.state_component[0]) if step % 10 == 0: if comm.rank == 0: logger.info(f"step: {step} " f"t: {time()-t_last_step} " f"L2: {l2norm}") if visualize: vis.write_parallel_vtk_file( comm, f"fld-wave-min-mpi-{{rank:03d}}-{step:04d}.vtu", [ ("u", event.state_component[0]), ("v", event.state_component[1:]), ]) t_last_step = time() # NOTE: These are here to ensure the solution is bounded for the # time interval specified assert l2norm < 1
def test_convergence_maxwell(actx_factory, order): """Test whether 3D Maxwell's actually converges""" actx = actx_factory() from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() dims = 3 ns = [4, 6, 8] for n in ns: mesh = mgen.generate_regular_rect_mesh(a=(0.0, ) * dims, b=(1.0, ) * dims, nelements_per_axis=(n, ) * dims) dcoll = DiscretizationCollection(actx, mesh, order=order) epsilon = 1 mu = 1 from grudge.models.em import get_rectangular_cavity_mode def analytic_sol(x, t=0): return get_rectangular_cavity_mode(actx, x, t, 1, (1, 2, 2)) nodes = thaw(dcoll.nodes(), actx) fields = analytic_sol(nodes, t=0) from grudge.models.em import MaxwellOperator maxwell_operator = MaxwellOperator(dcoll, epsilon, mu, flux_type=0.5, dimensions=dims) maxwell_operator.check_bc_coverage(mesh) def rhs(t, w): return maxwell_operator.operator(t, w) dt = maxwell_operator.estimate_rk4_timestep(actx, dcoll) final_t = dt * 5 nsteps = int(final_t / dt) from grudge.shortcuts import set_up_rk4 dt_stepper = set_up_rk4("w", dt, fields, rhs) logger.info("dt %.5e nsteps %5d", dt, nsteps) step = 0 for event in dt_stepper.run(t_end=final_t): if isinstance(event, dt_stepper.StateComputed): assert event.component_id == "w" esc = event.state_component step += 1 logger.debug("[%04d] t = %.5e", step, event.t) sol = analytic_sol(nodes, t=step * dt) total_error = op.norm(dcoll, esc - sol, 2) eoc_rec.add_data_point(1.0 / n, actx.to_numpy(total_error)) logger.info( "\n%s", eoc_rec.pretty_print(abscissa_label="h", error_label="L2 Error")) assert eoc_rec.order_estimate() > order
def main(write_output=True, order=4): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) dims = 2 from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(-0.5, ) * dims, b=(0.5, ) * dims, n=(16, ) * dims) if mesh.dim == 2: dt = 0.04 elif mesh.dim == 3: dt = 0.02 print("%d elements" % mesh.nelements) discr = DGDiscretizationWithBoundaries(cl_ctx, mesh, order=order) source_center = np.array([0.1, 0.22, 0.33])[:mesh.dim] source_width = 0.05 source_omega = 3 sym_x = sym.nodes(mesh.dim) sym_source_center_dist = sym_x - source_center sym_t = sym.ScalarVariable("t") from grudge.models.wave import StrongWaveOperator from meshmode.mesh import BTAG_ALL, BTAG_NONE op = StrongWaveOperator( -0.1, discr.dim, source_f=( sym.sin(source_omega * sym_t) * sym.exp(-np.dot(sym_source_center_dist, sym_source_center_dist) / source_width**2)), dirichlet_tag=BTAG_NONE, neumann_tag=BTAG_NONE, radiation_tag=BTAG_ALL, flux_type="upwind") queue = cl.CommandQueue(discr.cl_context) from pytools.obj_array import join_fields fields = join_fields(discr.zeros(queue), [discr.zeros(queue) for i in range(discr.dim)]) # FIXME #dt = op.estimate_rk4_timestep(discr, fields=fields) op.check_bc_coverage(mesh) # print(sym.pretty(op.sym_operator())) bound_op = bind(discr, op.sym_operator()) def rhs(t, w): return bound_op(queue, t=t, w=w) dt_stepper = set_up_rk4("w", dt, fields, rhs) final_t = 10 nsteps = int(final_t / dt) print("dt=%g nsteps=%d" % (dt, nsteps)) from grudge.shortcuts import make_visualizer vis = make_visualizer(discr, vis_order=order) step = 0 norm = bind(discr, sym.norm(2, sym.var("u"))) from time import time t_last_step = time() for event in dt_stepper.run(t_end=final_t): if isinstance(event, dt_stepper.StateComputed): assert event.component_id == "w" step += 1 print(step, event.t, norm(queue, u=event.state_component[0]), time() - t_last_step) if step % 10 == 0: vis.write_vtk_file("fld-wave-min-%04d.vtu" % step, [ ("u", event.state_component[0]), ("v", event.state_component[1:]), ]) t_last_step = time()
def test_convergence_advec(actx_factory, mesh_name, mesh_pars, op_type, flux_type, order, visualize=False): """Test whether 2D advection actually converges""" actx = actx_factory() from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() for mesh_par in mesh_pars: if mesh_name == "segment": mesh = mgen.generate_box_mesh([np.linspace(-1.0, 1.0, mesh_par)], order=order) dim = 1 dt_factor = 1.0 elif mesh_name == "disk": pytest.importorskip("meshpy") from meshpy.geometry import make_circle, GeometryBuilder from meshpy.triangle import MeshInfo, build geob = GeometryBuilder() geob.add_geometry(*make_circle(1)) mesh_info = MeshInfo() geob.set(mesh_info) mesh_info = build(mesh_info, max_volume=mesh_par) from meshmode.mesh.io import from_meshpy mesh = from_meshpy(mesh_info, order=1) dim = 2 dt_factor = 4 elif mesh_name.startswith("rect"): dim = int(mesh_name[-1:]) mesh = mgen.generate_regular_rect_mesh( a=(-0.5, ) * dim, b=(0.5, ) * dim, nelements_per_axis=(mesh_par, ) * dim, order=4) if dim == 2: dt_factor = 4 elif dim == 3: dt_factor = 2 else: raise ValueError("dt_factor not known for %dd" % dim) elif mesh_name.startswith("warped"): dim = int(mesh_name[-1:]) mesh = mgen.generate_warped_rect_mesh(dim, order=order, nelements_side=mesh_par) if dim == 2: dt_factor = 4 elif dim == 3: dt_factor = 2 else: raise ValueError("dt_factor not known for %dd" % dim) else: raise ValueError("invalid mesh name: " + mesh_name) v = np.array([0.27, 0.31, 0.1])[:dim] norm_v = la.norm(v) def f(x): return actx.np.sin(10 * x) def u_analytic(x, t=0): return f(-v.dot(x) / norm_v + t * norm_v) from grudge.models.advection import (StrongAdvectionOperator, WeakAdvectionOperator) from meshmode.mesh import BTAG_ALL dcoll = DiscretizationCollection(actx, mesh, order=order) op_class = { "strong": StrongAdvectionOperator, "weak": WeakAdvectionOperator }[op_type] adv_operator = op_class(dcoll, v, inflow_u=lambda t: u_analytic( thaw(dcoll.nodes(dd=BTAG_ALL), actx), t=t), flux_type=flux_type) nodes = thaw(dcoll.nodes(), actx) u = u_analytic(nodes, t=0) def rhs(t, u): return adv_operator.operator(t, u) if dim == 3: final_time = 0.1 else: final_time = 0.2 from grudge.dt_utils import h_max_from_volume h_max = h_max_from_volume(dcoll, dim=dcoll.ambient_dim) dt = dt_factor * h_max / order**2 nsteps = (final_time // dt) + 1 dt = final_time / nsteps + 1e-15 from grudge.shortcuts import set_up_rk4 dt_stepper = set_up_rk4("u", dt, u, rhs) last_u = None from grudge.shortcuts import make_visualizer vis = make_visualizer(dcoll) step = 0 for event in dt_stepper.run(t_end=final_time): if isinstance(event, dt_stepper.StateComputed): step += 1 logger.debug("[%04d] t = %.5f", step, event.t) last_t = event.t last_u = event.state_component if visualize: vis.write_vtk_file("fld-%s-%04d.vtu" % (mesh_par, step), [("u", event.state_component)]) error_l2 = op.norm(dcoll, last_u - u_analytic(nodes, t=last_t), 2) logger.info("h_max %.5e error %.5e", h_max, error_l2) eoc_rec.add_data_point(h_max, actx.to_numpy(error_l2)) logger.info( "\n%s", eoc_rec.pretty_print(abscissa_label="h", error_label="L2 Error")) if mesh_name.startswith("warped"): # NOTE: curvilinear meshes are hard assert eoc_rec.order_estimate() > order - 0.5 else: assert eoc_rec.order_estimate() > order
def main(write_output=True, order=4): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) dim = 2 resolution = 15 from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(-0.5, -0.5), b=(0.5, 0.5), n=(resolution, resolution), order=order) dt_factor = 5 h = 1 / resolution sym_x = sym.nodes(2) advec_v = join_fields(-1 * sym_x[1], sym_x[0]) / 2 flux_type = "upwind" source_center = np.array([0.1, 0.1]) source_width = 0.05 sym_x = sym.nodes(2) sym_source_center_dist = sym_x - source_center def f_gaussian(x): return sym.exp( -np.dot(sym_source_center_dist, sym_source_center_dist) / source_width**2) def f_step(x): return sym.If( sym.Comparison( np.dot(sym_source_center_dist, sym_source_center_dist), "<", (4 * source_width)**2), 1, 0) def u_analytic(x): return 0 from grudge.models.advection import VariableCoefficientAdvectionOperator from meshmode.discretization.poly_element import QuadratureSimplexGroupFactory # noqa discr = DGDiscretizationWithBoundaries( cl_ctx, mesh, order=order, quad_tag_to_group_factory={ #"product": None, "product": QuadratureSimplexGroupFactory(order=4 * order) }) op = VariableCoefficientAdvectionOperator(2, advec_v, u_analytic( sym.nodes(dim, sym.BTAG_ALL)), quad_tag="product", flux_type=flux_type) bound_op = bind( discr, op.sym_operator(), #debug_flags=["dump_sym_operator_stages"] ) u = bind(discr, f_gaussian(sym.nodes(dim)))(queue, t=0) def rhs(t, u): return bound_op(queue, t=t, u=u) dt = dt_factor * h / order**2 nsteps = (FINAL_TIME // dt) + 1 dt = FINAL_TIME / nsteps + 1e-15 from grudge.shortcuts import set_up_rk4 dt_stepper = set_up_rk4("u", dt, u, rhs) from grudge.shortcuts import make_visualizer vis = make_visualizer(discr, vis_order=2 * order) step = 0 for event in dt_stepper.run(t_end=FINAL_TIME): if isinstance(event, dt_stepper.StateComputed): step += 1 if step % 30 == 0: print(step) vis.write_vtk_file("fld-var-velocity-%04d.vtu" % step, [("u", event.state_component)])
def main(ctx_factory, dim=2, order=4, use_quad=False, visualize=False): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext( queue, allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)), force_device_scalars=True, ) # {{{ parameters # sphere radius radius = 1.0 # sphere resolution resolution = 64 if dim == 2 else 1 # final time final_time = np.pi # flux flux_type = "lf" # }}} # {{{ discretization if dim == 2: from meshmode.mesh.generation import make_curve_mesh, ellipse mesh = make_curve_mesh( lambda t: radius * ellipse(1.0, t), np.linspace(0.0, 1.0, resolution + 1), order) elif dim == 3: from meshmode.mesh.generation import generate_icosphere mesh = generate_icosphere(radius, order=4 * order, uniform_refinement_rounds=resolution) else: raise ValueError("unsupported dimension") discr_tag_to_group_factory = {} if use_quad: qtag = dof_desc.DISCR_TAG_QUAD else: qtag = None from meshmode.discretization.poly_element import \ default_simplex_group_factory, \ QuadratureSimplexGroupFactory discr_tag_to_group_factory[dof_desc.DISCR_TAG_BASE] = \ default_simplex_group_factory(base_dim=dim-1, order=order) if use_quad: discr_tag_to_group_factory[qtag] = \ QuadratureSimplexGroupFactory(order=4*order) from grudge import DiscretizationCollection dcoll = DiscretizationCollection( actx, mesh, discr_tag_to_group_factory=discr_tag_to_group_factory ) volume_discr = dcoll.discr_from_dd(dof_desc.DD_VOLUME) logger.info("ndofs: %d", volume_discr.ndofs) logger.info("nelements: %d", volume_discr.mesh.nelements) # }}} # {{{ Surface advection operator # velocity field x = thaw(dcoll.nodes(), actx) c = make_obj_array([-x[1], x[0], 0.0])[:dim] def f_initial_condition(x): return x[0] from grudge.models.advection import SurfaceAdvectionOperator adv_operator = SurfaceAdvectionOperator( dcoll, c, flux_type=flux_type, quad_tag=qtag ) u0 = f_initial_condition(x) def rhs(t, u): return adv_operator.operator(t, u) # check velocity is tangential from grudge.geometry import normal surf_normal = normal(actx, dcoll, dd=dof_desc.DD_VOLUME) error = op.norm(dcoll, c.dot(surf_normal), 2) logger.info("u_dot_n: %.5e", error) # }}} # {{{ time stepping # FIXME: dt estimate is not necessarily valid for surfaces dt = actx.to_numpy( 0.45 * adv_operator.estimate_rk4_timestep(actx, dcoll, fields=u0)) nsteps = int(final_time // dt) + 1 logger.info("dt: %.5e", dt) logger.info("nsteps: %d", nsteps) from grudge.shortcuts import set_up_rk4 dt_stepper = set_up_rk4("u", dt, u0, rhs) plot = Plotter(actx, dcoll, order, visualize=visualize) norm_u = actx.to_numpy(op.norm(dcoll, u0, 2)) step = 0 event = dt_stepper.StateComputed(0.0, 0, 0, u0) plot(event, "fld-surface-%04d" % 0) if visualize and dim == 3: from grudge.shortcuts import make_visualizer vis = make_visualizer(dcoll) vis.write_vtk_file( "fld-surface-velocity.vtu", [ ("u", c), ("n", surf_normal) ], overwrite=True ) df = dof_desc.DOFDesc(FACE_RESTR_INTERIOR) face_discr = dcoll.discr_from_dd(df) face_normal = thaw(dcoll.normal(dd=df), actx) from meshmode.discretization.visualization import make_visualizer vis = make_visualizer(actx, face_discr) vis.write_vtk_file("fld-surface-face-normals.vtu", [ ("n", face_normal) ], overwrite=True) for event in dt_stepper.run(t_end=final_time, max_steps=nsteps + 1): if not isinstance(event, dt_stepper.StateComputed): continue step += 1 if step % 10 == 0: norm_u = actx.to_numpy(op.norm(dcoll, event.state_component, 2)) plot(event, "fld-surface-%04d" % step) logger.info("[%04d] t = %.5f |u| = %.5e", step, event.t, norm_u) # NOTE: These are here to ensure the solution is bounded for the # time interval specified assert norm_u < 3
def main(ctx_factory, dim=2, order=4, product_tag=None, visualize=False): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) # {{{ parameters # domain [0, d]^dim d = 1.0 # number of points in each dimension npoints = 25 # grid spacing h = d / npoints # cfl dt_factor = 1.0 # finale time final_time = 0.5 # time steps dt = dt_factor * h / order**2 nsteps = int(final_time // dt) + 1 dt = final_time / nsteps + 1.0e-15 # flux flux_type = "upwind" # velocity field sym_x = sym.nodes(dim) if dim == 1: c = sym_x else: # solid body rotation c = flat_obj_array(np.pi * (d / 2 - sym_x[1]), np.pi * (sym_x[0] - d / 2), 0)[:dim] # }}} # {{{ discretization from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(0, ) * dim, b=(d, ) * dim, npoints_per_axis=(npoints, ) * dim, order=order) from meshmode.discretization.poly_element import \ QuadratureSimplexGroupFactory if product_tag: discr_tag_to_group_factory = { product_tag: QuadratureSimplexGroupFactory(order=4 * order) } else: discr_tag_to_group_factory = {} from grudge import DiscretizationCollection discr = DiscretizationCollection( actx, mesh, order=order, discr_tag_to_group_factory=discr_tag_to_group_factory) # }}} # {{{ symbolic operators # gaussian parameters source_center = np.array([0.5, 0.75, 0.0])[:dim] source_width = 0.05 dist_squared = np.dot(sym_x - source_center, sym_x - source_center) def f_gaussian(x): return sym.exp(-dist_squared / source_width**2) def f_step(x): return sym.If(sym.Comparison(dist_squared, "<", (4 * source_width)**2), 1, 0) def u_bc(x): return 0.0 from grudge.models.advection import VariableCoefficientAdvectionOperator op = VariableCoefficientAdvectionOperator(c, u_bc(sym.nodes(dim, BTAG_ALL)), quad_tag=product_tag, flux_type=flux_type) bound_op = bind(discr, op.sym_operator()) u = bind(discr, f_gaussian(sym.nodes(dim)))(actx, t=0) def rhs(t, u): return bound_op(t=t, u=u) # }}} # {{{ time stepping from grudge.shortcuts import set_up_rk4 dt_stepper = set_up_rk4("u", dt, u, rhs) plot = Plotter(actx, discr, order, visualize=visualize, ylim=[-0.1, 1.1]) step = 0 norm = bind(discr, sym.norm(2, sym.var("u"))) for event in dt_stepper.run(t_end=final_time): if not isinstance(event, dt_stepper.StateComputed): continue if step % 10 == 0: norm_u = norm(u=event.state_component) plot(event, "fld-var-velocity-%04d" % step) step += 1 logger.info("[%04d] t = %.5f |u| = %.5e", step, event.t, norm_u)
def main(ctx_factory, dim=2, order=4, visualize=False): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext( queue, allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)), force_device_scalars=True, ) 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=(20, ) * dim) dcoll = DiscretizationCollection(actx, mesh, order=order) def source_f(actx, dcoll, t=0): source_center = np.array([0.1, 0.22, 0.33])[:dcoll.dim] source_width = 0.05 source_omega = 3 nodes = thaw(dcoll.nodes(), actx) source_center_dist = flat_obj_array( [nodes[i] - source_center[i] for i in range(dcoll.dim)]) return (np.sin(source_omega * t) * actx.np.exp( -np.dot(source_center_dist, source_center_dist) / source_width**2)) x = thaw(dcoll.nodes(), actx) ones = dcoll.zeros(actx) + 1 c = actx.np.where(np.dot(x, x) < 0.15, 0.1 * ones, 0.2 * ones) from grudge.models.wave import VariableCoefficientWeakWaveOperator from meshmode.mesh import BTAG_ALL, BTAG_NONE wave_op = VariableCoefficientWeakWaveOperator(dcoll, c, source_f=source_f, dirichlet_tag=BTAG_NONE, neumann_tag=BTAG_NONE, radiation_tag=BTAG_ALL, flux_type="upwind") fields = flat_obj_array(dcoll.zeros(actx), [dcoll.zeros(actx) for i in range(dcoll.dim)]) wave_op.check_bc_coverage(mesh) def rhs(t, w): return wave_op.operator(t, w) dt = 2 / 3 * wave_op.estimate_rk4_timestep(actx, dcoll, fields=fields) dt_stepper = set_up_rk4("w", dt, fields, rhs) final_t = 1 nsteps = int(final_t / dt) + 1 logger.info("dt=%g nsteps=%d", dt, nsteps) from grudge.shortcuts import make_visualizer vis = make_visualizer(dcoll) step = 0 def norm(u): return op.norm(dcoll, u, 2) from time import time t_last_step = time() if visualize: u = fields[0] v = fields[1:] vis.write_vtk_file(f"fld-var-propogation-speed-{step:04d}.vtu", [ ("u", u), ("v", v), ("c", c), ]) for event in dt_stepper.run(t_end=final_t): if isinstance(event, dt_stepper.StateComputed): assert event.component_id == "w" step += 1 if step % 10 == 0: logger.info(f"step: {step} t: {time()-t_last_step} " f"L2: {norm(u=event.state_component[0])}") if visualize: vis.write_vtk_file( f"fld-var-propogation-speed-{step:04d}.vtu", [ ("u", event.state_component[0]), ("v", event.state_component[1:]), ("c", c), ]) t_last_step = time() # NOTE: These are here to ensure the solution is bounded for the # time interval specified assert norm(u=event.state_component[0]) < 1
def test_convergence_advec(ctx_factory, mesh_name, mesh_pars, op_type, flux_type, order, visualize=False): """Test whether 2D advection actually converges""" cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) from pytools.convergence import EOCRecorder eoc_rec = EOCRecorder() for mesh_par in mesh_pars: if mesh_name == "segment": from meshmode.mesh.generation import generate_box_mesh mesh = generate_box_mesh([np.linspace(-1.0, 1.0, mesh_par)], order=order) dim = 1 dt_factor = 1.0 elif mesh_name == "disk": pytest.importorskip("meshpy") from meshpy.geometry import make_circle, GeometryBuilder from meshpy.triangle import MeshInfo, build geob = GeometryBuilder() geob.add_geometry(*make_circle(1)) mesh_info = MeshInfo() geob.set(mesh_info) mesh_info = build(mesh_info, max_volume=mesh_par) from meshmode.mesh.io import from_meshpy mesh = from_meshpy(mesh_info, order=1) dim = 2 dt_factor = 4 elif mesh_name.startswith("rect"): dim = int(mesh_name[4:]) from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(-0.5, ) * dim, b=(0.5, ) * dim, n=(mesh_par, ) * dim, order=4) if dim == 2: dt_factor = 4 elif dim == 3: dt_factor = 2 else: raise ValueError("dt_factor not known for %dd" % dim) else: raise ValueError("invalid mesh name: " + mesh_name) v = np.array([0.27, 0.31, 0.1])[:dim] norm_v = la.norm(v) def f(x): return sym.sin(10 * x) def u_analytic(x): return f(-v.dot(x) / norm_v + sym.var("t", sym.DD_SCALAR) * norm_v) from grudge.models.advection import (StrongAdvectionOperator, WeakAdvectionOperator) discr = DGDiscretizationWithBoundaries(actx, mesh, order=order) op_class = { "strong": StrongAdvectionOperator, "weak": WeakAdvectionOperator, }[op_type] op = op_class(v, inflow_u=u_analytic(sym.nodes(dim, sym.BTAG_ALL)), flux_type=flux_type) bound_op = bind(discr, op.sym_operator()) u = bind(discr, u_analytic(sym.nodes(dim)))(actx, t=0) def rhs(t, u): return bound_op(t=t, u=u) if dim == 3: final_time = 0.1 else: final_time = 0.2 h_max = bind(discr, sym.h_max_from_volume(discr.ambient_dim))(actx) dt = dt_factor * h_max / order**2 nsteps = (final_time // dt) + 1 dt = final_time / nsteps + 1e-15 from grudge.shortcuts import set_up_rk4 dt_stepper = set_up_rk4("u", dt, u, rhs) last_u = None from grudge.shortcuts import make_visualizer vis = make_visualizer(discr, vis_order=order) step = 0 for event in dt_stepper.run(t_end=final_time): if isinstance(event, dt_stepper.StateComputed): step += 1 logger.debug("[%04d] t = %.5f", step, event.t) last_t = event.t last_u = event.state_component if visualize: vis.write_vtk_file("fld-%s-%04d.vtu" % (mesh_par, step), [("u", event.state_component)]) error_l2 = bind(discr, sym.norm(2, sym.var("u") - u_analytic(sym.nodes(dim))))( t=last_t, u=last_u) logger.info("h_max %.5e error %.5e", h_max, error_l2) eoc_rec.add_data_point(h_max, error_l2) logger.info( "\n%s", eoc_rec.pretty_print(abscissa_label="h", error_label="L2 Error")) assert eoc_rec.order_estimate() > order
def main(ctx_factory, dim=2, order=4, use_quad=False, visualize=False, flux_type="upwind"): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext( queue, allocator=cl_tools.MemoryPool(cl_tools.ImmediateAllocator(queue)), force_device_scalars=True, ) # {{{ parameters # domain [0, d]^dim d = 1.0 # number of points in each dimension npoints = 25 # final time final_time = 1 if use_quad: qtag = dof_desc.DISCR_TAG_QUAD else: qtag = None # }}} # {{{ discretization from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(0, ) * dim, b=(d, ) * dim, npoints_per_axis=(npoints, ) * dim, order=order) from meshmode.discretization.poly_element import \ QuadratureSimplexGroupFactory if use_quad: discr_tag_to_group_factory = { qtag: QuadratureSimplexGroupFactory(order=4 * order) } else: discr_tag_to_group_factory = {} from grudge import DiscretizationCollection dcoll = DiscretizationCollection( actx, mesh, order=order, discr_tag_to_group_factory=discr_tag_to_group_factory) # }}} # {{{ advection operator # gaussian parameters def f_halfcircle(x): source_center = np.array([d / 2, d / 2, d / 2])[:dim] dist = x - source_center return ((0.5 + 0.5 * actx.np.tanh(500 * (-np.dot(dist, dist) + 0.4**2))) * (0.5 + 0.5 * actx.np.tanh(500 * (dist[0])))) def zero_inflow_bc(dtag, t=0): dd = dof_desc.DOFDesc(dtag, qtag) return dcoll.discr_from_dd(dd).zeros(actx) from grudge.models.advection import VariableCoefficientAdvectionOperator x = thaw(dcoll.nodes(), actx) # velocity field if dim == 1: c = x else: # solid body rotation c = flat_obj_array(np.pi * (d / 2 - x[1]), np.pi * (x[0] - d / 2), 0)[:dim] adv_operator = VariableCoefficientAdvectionOperator( dcoll, c, inflow_u=lambda t: zero_inflow_bc(BTAG_ALL, t), quad_tag=qtag, flux_type=flux_type) u = f_halfcircle(x) def rhs(t, u): return adv_operator.operator(t, u) dt = actx.to_numpy( adv_operator.estimate_rk4_timestep(actx, dcoll, fields=u)) logger.info("Timestep size: %g", dt) # }}} # {{{ time stepping from grudge.shortcuts import set_up_rk4 dt_stepper = set_up_rk4("u", dt, u, rhs) plot = Plotter(actx, dcoll, order, visualize=visualize, ylim=[-0.1, 1.1]) step = 0 for event in dt_stepper.run(t_end=final_time): if not isinstance(event, dt_stepper.StateComputed): continue if step % 10 == 0: norm_u = actx.to_numpy(op.norm(dcoll, event.state_component, 2)) plot(event, "fld-var-velocity-%04d" % step) step += 1 logger.info("[%04d] t = %.5f |u| = %.5e", step, event.t, norm_u) # NOTE: These are here to ensure the solution is bounded for the # time interval specified assert norm_u < 1
def main(ctx_factory, dim=2, order=4, visualize=False): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) # {{{ parameters # domain [-d/2, d/2]^dim d = 1.0 # number of points in each dimension npoints = 20 # grid spacing h = d / npoints # cfl dt_factor = 2.0 # final time final_time = 1.0 # compute number of steps dt = dt_factor * h / order**2 nsteps = int(final_time // dt) + 1 dt = final_time / nsteps + 1.0e-15 # velocity field c = np.array([0.5] * dim) norm_c = la.norm(c) # flux flux_type = "central" # }}} # {{{ discretization from meshmode.mesh.generation import generate_box_mesh mesh = generate_box_mesh( [np.linspace(-d / 2, d / 2, npoints) for _ in range(dim)], order=order) from grudge import DiscretizationCollection discr = DiscretizationCollection(actx, mesh, order=order) # }}} # {{{ symbolic operators def f(x): return sym.sin(3 * x) def u_analytic(x): t = sym.var("t", dof_desc.DD_SCALAR) return f(-np.dot(c, x) / norm_c + t * norm_c) from grudge.models.advection import WeakAdvectionOperator op = WeakAdvectionOperator(c, inflow_u=u_analytic(sym.nodes(dim, BTAG_ALL)), flux_type=flux_type) bound_op = bind(discr, op.sym_operator()) u = bind(discr, u_analytic(sym.nodes(dim)))(actx, t=0) def rhs(t, u): return bound_op(t=t, u=u) # }}} # {{{ time stepping from grudge.shortcuts import set_up_rk4 dt_stepper = set_up_rk4("u", dt, u, rhs) plot = Plotter(actx, discr, order, visualize=visualize, ylim=[-1.1, 1.1]) norm = bind(discr, sym.norm(2, sym.var("u"))) step = 0 norm_u = 0.0 for event in dt_stepper.run(t_end=final_time): if not isinstance(event, dt_stepper.StateComputed): continue if step % 10 == 0: norm_u = norm(u=event.state_component) plot(event, "fld-weak-%04d" % step) step += 1 logger.info("[%04d] t = %.5f |u| = %.5e", step, event.t, norm_u)
def main(write_output=True, order=4): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) comm = MPI.COMM_WORLD num_parts = comm.Get_size() from meshmode.distributed import MPIMeshDistributor, get_partition_by_pymetis mesh_dist = MPIMeshDistributor(comm) if mesh_dist.is_mananger_rank(): dims = 2 from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(-0.5, ) * dims, b=(0.5, ) * dims, n=(16, ) * dims) print("%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() discr = DGDiscretizationWithBoundaries(actx, local_mesh, order=order, mpi_communicator=comm) if local_mesh.dim == 2: dt = 0.04 elif local_mesh.dim == 3: dt = 0.02 source_center = np.array([0.1, 0.22, 0.33])[:local_mesh.dim] source_width = 0.05 source_omega = 3 sym_x = sym.nodes(local_mesh.dim) sym_source_center_dist = sym_x - source_center sym_t = sym.ScalarVariable("t") from grudge.models.wave import StrongWaveOperator from meshmode.mesh import BTAG_ALL, BTAG_NONE op = StrongWaveOperator( -0.1, discr.dim, source_f=( sym.sin(source_omega * sym_t) * sym.exp(-np.dot(sym_source_center_dist, sym_source_center_dist) / source_width**2)), dirichlet_tag=BTAG_NONE, neumann_tag=BTAG_NONE, radiation_tag=BTAG_ALL, flux_type="upwind") from pytools.obj_array import flat_obj_array fields = flat_obj_array(discr.zeros(actx), [discr.zeros(actx) for i in range(discr.dim)]) # FIXME #dt = op.estimate_rk4_timestep(discr, fields=fields) op.check_bc_coverage(local_mesh) # print(sym.pretty(op.sym_operator())) bound_op = bind(discr, op.sym_operator()) def rhs(t, w): return bound_op(t=t, w=w) dt_stepper = set_up_rk4("w", dt, fields, rhs) final_t = 10 nsteps = int(final_t / dt) print("dt=%g nsteps=%d" % (dt, nsteps)) from grudge.shortcuts import make_visualizer vis = make_visualizer(discr, vis_order=order) step = 0 norm = bind(discr, sym.norm(2, sym.var("u"))) from time import time t_last_step = time() rank = comm.Get_rank() for event in dt_stepper.run(t_end=final_t): if isinstance(event, dt_stepper.StateComputed): assert event.component_id == "w" step += 1 print(step, event.t, norm(u=event.state_component[0]), time() - t_last_step) if step % 10 == 0: vis.write_vtk_file( "fld-wave-min-mpi-%03d-%04d.vtu" % ( rank, step, ), [ ("u", event.state_component[0]), ("v", event.state_component[1:]), ]) t_last_step = time()
def main(ctx_factory, dim=2, order=4, product_tag=None, visualize=False): cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) # {{{ parameters # sphere radius radius = 1.0 # sphere resolution resolution = 64 if dim == 2 else 1 # cfl dt_factor = 2.0 # final time final_time = np.pi # velocity field sym_x = sym.nodes(dim) c = make_obj_array([-sym_x[1], sym_x[0], 0.0])[:dim] # flux flux_type = "lf" # }}} # {{{ discretization if dim == 2: from meshmode.mesh.generation import make_curve_mesh, ellipse mesh = make_curve_mesh(lambda t: radius * ellipse(1.0, t), np.linspace(0.0, 1.0, resolution + 1), order) elif dim == 3: from meshmode.mesh.generation import generate_icosphere mesh = generate_icosphere(radius, order=4 * order, uniform_refinement_rounds=resolution) else: raise ValueError("unsupported dimension") discr_tag_to_group_factory = {} if product_tag == "none": product_tag = None else: product_tag = dof_desc.DISCR_TAG_QUAD from meshmode.discretization.poly_element import \ PolynomialWarpAndBlendGroupFactory, \ QuadratureSimplexGroupFactory discr_tag_to_group_factory[dof_desc.DISCR_TAG_BASE] = \ PolynomialWarpAndBlendGroupFactory(order) if product_tag: discr_tag_to_group_factory[product_tag] = \ QuadratureSimplexGroupFactory(order=4*order) from grudge import DiscretizationCollection discr = DiscretizationCollection( actx, mesh, discr_tag_to_group_factory=discr_tag_to_group_factory) volume_discr = discr.discr_from_dd(dof_desc.DD_VOLUME) logger.info("ndofs: %d", volume_discr.ndofs) logger.info("nelements: %d", volume_discr.mesh.nelements) # }}} # {{{ symbolic operators def f_initial_condition(x): return x[0] from grudge.models.advection import SurfaceAdvectionOperator op = SurfaceAdvectionOperator(c, flux_type=flux_type, quad_tag=product_tag) bound_op = bind(discr, op.sym_operator()) u0 = bind(discr, f_initial_condition(sym_x))(actx, t=0) def rhs(t, u): return bound_op(actx, t=t, u=u) # check velocity is tangential sym_normal = sym.surface_normal(dim, dim=dim - 1, dd=dof_desc.DD_VOLUME).as_vector() error = bind(discr, sym.norm(2, c.dot(sym_normal)))(actx) logger.info("u_dot_n: %.5e", error) # }}} # {{{ time stepping # compute time step h_min = bind(discr, sym.h_max_from_volume(discr.ambient_dim, dim=discr.dim))(actx) dt = dt_factor * h_min / order**2 nsteps = int(final_time // dt) + 1 dt = final_time / nsteps + 1.0e-15 logger.info("dt: %.5e", dt) logger.info("nsteps: %d", nsteps) from grudge.shortcuts import set_up_rk4 dt_stepper = set_up_rk4("u", dt, u0, rhs) plot = Plotter(actx, discr, order, visualize=visualize) norm = bind(discr, sym.norm(2, sym.var("u"))) norm_u = norm(actx, u=u0) step = 0 event = dt_stepper.StateComputed(0.0, 0, 0, u0) plot(event, "fld-surface-%04d" % 0) if visualize and dim == 3: from grudge.shortcuts import make_visualizer vis = make_visualizer(discr) vis.write_vtk_file("fld-surface-velocity.vtu", [("u", bind(discr, c)(actx)), ("n", bind(discr, sym_normal)(actx))], overwrite=True) df = dof_desc.DOFDesc(FACE_RESTR_INTERIOR) face_discr = discr.connection_from_dds(dof_desc.DD_VOLUME, df).to_discr face_normal = bind( discr, sym.normal(df, face_discr.ambient_dim, dim=face_discr.dim))(actx) from meshmode.discretization.visualization import make_visualizer vis = make_visualizer(actx, face_discr) vis.write_vtk_file("fld-surface-face-normals.vtu", [("n", face_normal)], overwrite=True) for event in dt_stepper.run(t_end=final_time, max_steps=nsteps + 1): if not isinstance(event, dt_stepper.StateComputed): continue step += 1 if step % 10 == 0: norm_u = norm(actx, u=event.state_component) plot(event, "fld-surface-%04d" % step) logger.info("[%04d] t = %.5f |u| = %.5e", step, event.t, norm_u) plot(event, "fld-surface-%04d" % step)
def main(write_output=True, order=4): cl_ctx = cl.create_some_context() queue = cl.CommandQueue(cl_ctx) dim = 2 from meshmode.mesh.generation import generate_regular_rect_mesh mesh = generate_regular_rect_mesh(a=(-0.5, -0.5), b=(0.5, 0.5), n=(20, 20), order=order) dt_factor = 4 h = 1 / 20 discr = DGDiscretizationWithBoundaries(cl_ctx, mesh, order=order) c = np.array([0.1, 0.1]) norm_c = la.norm(c) flux_type = "central" def f(x): return sym.sin(3 * x) def u_analytic(x): return f(-np.dot(c, x) / norm_c + sym.var("t", sym.DD_SCALAR) * norm_c) from grudge.models.advection import WeakAdvectionOperator discr = DGDiscretizationWithBoundaries(cl_ctx, mesh, order=order) op = WeakAdvectionOperator(c, inflow_u=u_analytic(sym.nodes( dim, sym.BTAG_ALL)), flux_type=flux_type) bound_op = bind(discr, op.sym_operator()) u = bind(discr, u_analytic(sym.nodes(dim)))(queue, t=0) def rhs(t, u): return bound_op(queue, t=t, u=u) final_time = 0.3 dt = dt_factor * h / order**2 nsteps = (final_time // dt) + 1 dt = final_time / nsteps + 1e-15 from grudge.shortcuts import set_up_rk4 dt_stepper = set_up_rk4("u", dt, u, rhs) from grudge.shortcuts import make_visualizer vis = make_visualizer(discr, vis_order=order) step = 0 for event in dt_stepper.run(t_end=final_time): if isinstance(event, dt_stepper.StateComputed): step += 1 #print(step, event.t, norm(queue, u=event.state_component[0])) vis.write_vtk_file("fld-weak-%04d.vtu" % step, [("u", event.state_component)])