def conv_test(descr, use_quad): logger.info("-" * 75) logger.info(descr) logger.info("-" * 75) eoc_rec = EOCRecorder() if use_quad: qtag = dof_desc.DISCR_TAG_QUAD else: qtag = None ns = [20, 25] for n in ns: mesh = mgen.generate_regular_rect_mesh(a=(-0.5, ) * dims, b=(0.5, ) * dims, nelements_per_axis=(n, ) * dims, order=order) if use_quad: discr_tag_to_group_factory = { qtag: QuadratureSimplexGroupFactory(order=4 * order) } else: discr_tag_to_group_factory = {} dcoll = DiscretizationCollection( actx, mesh, order=order, discr_tag_to_group_factory=discr_tag_to_group_factory) nodes = thaw(dcoll.nodes(), actx) def zero_inflow(dtag, t=0): dd = dof_desc.DOFDesc(dtag, qtag) return dcoll.discr_from_dd(dd).zeros(actx) adv_op = VariableCoefficientAdvectionOperator( dcoll, flat_obj_array(-1 * nodes[1], nodes[0]), inflow_u=lambda t: zero_inflow(BTAG_ALL, t=t), flux_type="upwind", quad_tag=qtag) total_error = op.norm(dcoll, adv_op.operator(0, gaussian_mode(nodes)), 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")) return eoc_rec.order_estimate(), np.array( [x[1] for x in eoc_rec.history])
def test_improvement_quadrature(ctx_factory, order): """Test whether quadrature improves things and converges""" from meshmode.mesh.generation import generate_regular_rect_mesh from grudge.models.advection import VariableCoefficientAdvectionOperator from pytools.convergence import EOCRecorder from meshmode.discretization.poly_element import QuadratureSimplexGroupFactory cl_ctx = ctx_factory() queue = cl.CommandQueue(cl_ctx) actx = PyOpenCLArrayContext(queue) dims = 2 sym_nds = sym.nodes(dims) advec_v = flat_obj_array(-1 * sym_nds[1], sym_nds[0]) flux = "upwind" op = VariableCoefficientAdvectionOperator(advec_v, 0, flux_type=flux) def gaussian_mode(): source_width = 0.1 sym_x = sym.nodes(2) return sym.exp(-np.dot(sym_x, sym_x) / source_width**2) def conv_test(descr, use_quad): logger.info("-" * 75) logger.info(descr) logger.info("-" * 75) eoc_rec = EOCRecorder() ns = [20, 25] for n in ns: mesh = generate_regular_rect_mesh(a=(-0.5, ) * dims, b=(0.5, ) * dims, n=(n, ) * dims, order=order) if use_quad: quad_tag_to_group_factory = { "product": QuadratureSimplexGroupFactory(order=4 * order) } else: quad_tag_to_group_factory = {"product": None} discr = DGDiscretizationWithBoundaries( actx, mesh, order=order, quad_tag_to_group_factory=quad_tag_to_group_factory) bound_op = bind(discr, op.sym_operator()) fields = bind(discr, gaussian_mode())(actx, t=0) norm = bind(discr, sym.norm(2, sym.var("u"))) esc = bound_op(u=fields) total_error = norm(u=esc) 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")) return eoc_rec.order_estimate(), np.array( [x[1] for x in eoc_rec.history]) eoc, errs = conv_test("no quadrature", False) q_eoc, q_errs = conv_test("with quadrature", True) assert q_eoc > eoc assert (q_errs < errs).all() assert q_eoc > order
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, 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(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)])